본문 바로가기
까망 동네/디자인 패턴

[디자인 패턴] 경량 패턴 (Flyweight Pattern)

by 까망 하르방 2023. 11. 12.
반응형

🎈 플라이웨이트 패턴 (Flyweight Pattern)

 객체를 공유하여 메모리 사용을 최적화하는 패턴

    플라이웨이트 패턴은 모든 객체를 일일이 생성하지 않고

    중복되는 부분을 공유해서 메모리를 가볍게 만드는 패턴

 Flyweight = "Fly 가벼운 + Weight 무게"라는 의미로

 (복싱의 체급에서 유래되었다.)

 게임 개발, 웹 브라우저 캐시 등에 활용 가능

• 디자인 패턴 중 구조 패턴

 

💻 디자인 패턴(Design Pattern)이란?

👨‍💻 디자인 패턴(Design Pattern)이란? • SW 개발 방법 중에서도 구조적인 문제 해결에 목적을 둔다. • 알고리즘과 같이 특정 문제를 해결하는 Logic 형태보다는 특정 상황에 적용할 수 있는 방

zoosso.tistory.com


 

[예제 코드]

웹 브라우저 캐시 시스템을 구현하여 이미지를 공유하는 예제

#include <iostream>
#include <map>
#include <string>

int usedMemory = 0;

class Image {
public:
    Image(const std::string& url) : url(url) {
        // URL을 통한 로딩 작업은 생략 (비용이 크다고 가정)
        std::cout << "Loading URL: " << url << std::endl;
    }

    void display() {
        std::cout << "Displaying image: " << url << std::endl;
    }

private:
    std::string url;
};


class ImageFactory {
public:
    Image* getImage(const std::string& url) {
        // 이미 로드한 경우 캐시된 이미지 반환
        if (imageCache.find(url) != imageCache.end()) {
            std::cout << "[이미 존재]: " << url << std::endl;
            return imageCache[url];
        }
        else {
            // 이미지를 로드하고 캐시에 저장
            Image* newImage = new Image(url);
            imageCache[url] = newImage;
            usedMemory += sizeof(newImage);
            return newImage;
        }
    }

private:
    std::map<std::string, Image*> imageCache;
};

int main() {
    ImageFactory imageFactory;

    // 이미지 요청
    Image* image1 = imageFactory.getImage("까망.jpg");
    Image* image2 = imageFactory.getImage("하르방.jpg");
    Image* image3 = imageFactory.getImage("까망.jpg"); // 이미 로드된 이미지와 동일한 URL

    // 이미지 표시
    image1->display();
    image2->display();
    image3->display();

    return 0;
}

 

경량 패턴 예시

 

동일한 URL을 가진 이미지가 여러 번 요청되어도

이미지는 한 번만 로드되고, 이후 요청에서는 캐시된 이미지가 반환


🎈 플라이웨이트 패턴 장단점

+ 메모리 최적화: 여러 객체가 동일한 데이터에 접근할 때, 데이터의 중복 복제를 방지한다.

+ 성능 향상: 공유 데이터를 사용하므로 객체 생성 및 소멸 시간을 줄일 수 있다.

+ 빠른 객체 생성: 새로운 객체를 생성 대신 이미 존재하는 객체를 공유하기에 생성/초기화 비용을 줄일 수 있다.

 

- 데이터 관리: 여러 객체가 데이터를 공유하므로 데이터가 변경되면 예상치 못한 부작용이 발생할 수 있다.

 

 

📌 경량패턴은 언제 활용될까?

 공통적인 인스턴스를 많이 생성하는 경우

 생성된 객체가 오래도록 메모리에 상주하는 경우

 자주 변하지 않는 속성을 재사용하는 경우

 

 

[예제 코드]

#include <iostream>
#include <string>
#include <map>
#include <vector>

class FlyweightApple {
public:
    FlyweightApple() : region(""), grade("") {}

    FlyweightApple(const std::string& _region) : region(_region), grade("") {}

    std::string getData() const {
        return region;
    }

    void setGrade(const std::string& _grade) {
        grade = _grade;
    }

    std::string getGrade() const {
        return grade;
    }

private:
    std::string region;
    std::string grade;
};

class FlyweightAppleFactory {
public:
    FlyweightApple getFlyweightApple(const std::string& region) {
        if (flyweights.find(region) != flyweights.end()) {
            return flyweights[region];
        }
        else {
            FlyweightApple newApple(region);
            flyweights[region] = newApple;
            return newApple;
        }
    }

private:
    std::map<std::string, FlyweightApple> flyweights;
};

int main() {
    FlyweightAppleFactory factory;
    std::vector<FlyweightApple> mart;

    mart.push_back(factory.getFlyweightApple("청송"));
    mart.push_back(factory.getFlyweightApple("안동"));
    mart.push_back(factory.getFlyweightApple("영주"));
    mart.push_back(factory.getFlyweightApple("청송"));
    mart.push_back(factory.getFlyweightApple("안동"));

    // 같은 지역의 사과이더라도 다른 등급으로 책정
    mart[1].setGrade("A");
    mart[4].setGrade("B");

    for (const FlyweightApple& apple : mart) {
        std::cout << "지역: " << apple.getData() << ", 등급: " << apple.getGrade() << std::endl;
    }

    return 0;
}

 

플라이웨이트 패턴 예시

 

사과(Apple)은 공통적으로 생산지 지역(region) 속성을 가진다.

같은 지역이라도 사과마다 등급 속성을 다르게 가질 수 있다.

 

이처럼 공용 속성을 가지는 대상인 "지역별 사과"를

경량 패턴을 통해 빠르게 생산할 수 있다.

만들어진 사과의 생산지가 바뀌지 않는 것이 일반적이다.


 

 

📌 Intrinsic & Extrinsic

Intrinsic (변하지 않는 속성)

 intrinsic = '고유한, 본질적인'

 어떠한 상황에서도 변하지 않는 정보

 값이 고정되어 있기에 공유 가능한 객체 상태 (Sharable)

 다른 표현으로 Context와 독립적이라고함

 

Extrinsic state (자주 변하는 속성)

 extrinsic = '외적인, 비본질적인'

 인스턴스를 두는 장소나 상황에 따라서 변화하는 정보

 값이 어떻게 변화할지 모르기 때문에 쉽게 공유할 수는 없다. (UnSharable)

 

 

🎈 다른 디자인 패턴과 비교

• 싱글턴 (Singleton)  

플라이웨이트 패턴과 마찬가지로 메모리 최적화를 목표로 한다.

싱글턴 패턴은 객체를 하나만 생성하여 메모리를 최적화 한다면

경량 패턴은 객체 간 중복 데이터를 공유하여 메모리 낭비를 방지한다.

 

또한 싱글턴 패턴은 특정 클래스 인스턴스 하나만 생성하여 전역 접근성 제공한다면

경량 패턴은 인스턴스 개수가 다수가 될 수 있다.

반응형

댓글