🎈 플라이웨이트 패턴 (Flyweight Pattern)
• 객체를 공유하여 메모리 사용을 최적화하는 패턴
플라이웨이트 패턴은 모든 객체를 일일이 생성하지 않고
중복되는 부분을 공유해서 메모리를 가볍게 만드는 패턴
• Flyweight = "Fly 가벼운 + Weight 무게"라는 의미로
(복싱의 체급에서 유래되었다.)
• 게임 개발, 웹 브라우저 캐시 등에 활용 가능
• 디자인 패턴 중 구조 패턴
[예제 코드]
웹 브라우저 캐시 시스템을 구현하여 이미지를 공유하는 예제
#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)
🎈 다른 디자인 패턴과 비교
플라이웨이트 패턴과 마찬가지로 메모리 최적화를 목표로 한다.
싱글턴 패턴은 객체를 하나만 생성하여 메모리를 최적화 한다면
경량 패턴은 객체 간 중복 데이터를 공유하여 메모리 낭비를 방지한다.
또한 싱글턴 패턴은 특정 클래스 인스턴스 하나만 생성하여 전역 접근성 제공한다면
경량 패턴은 인스턴스 개수가 다수가 될 수 있다.
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 반복자 패턴(Iterator Pattern) (33) | 2023.11.14 |
---|---|
[디자인패턴] 방문자 패턴 (Visitor Pattern) (3) | 2023.11.13 |
[디자인 패턴] 프록시 패턴 (Proxy Pattern) (3) | 2023.11.11 |
[디자인 패턴] 메멘토 패턴 (Memento Pattern) (1) | 2023.11.10 |
[디자인패턴] 퍼사드 패턴 (Facade Pattern) (54) | 2023.11.09 |
댓글