플리웨이트 패턴이란, 변하지 않는 속성과 자주 변하는 속성을 분리해서 변하지 않는 속성을 재사용 가능한 객체 인스턴스로 공유시켜 메모리 사용량을 최소화하는 구조패턴이다.
중요한점은 캐시 개념을 적용시켜서 코드로 패턴화 한것이다(ex, Map 자료구조를 사용해서 이전에 생성했던 정보를 기억)
이름에 알 수 있듯이 메모리를 가볍게 만든다는 의미로 쓰인다.
Flyweight = 경량
경량 패턴이라고도 불린다.
예를 들어서 폭탄 떨어뜨리기 게임을 생각하자, 폭탄이라는 객체는 중복되서 사용되게 된다.
하지만 폭탄의 모양이나 색은 고정값으로 공유가 가능하지만 좌표값은 모든 폭탄에 따라 다르게 변화하기 때문에 공유될 수 없다.
폭탄의 형태나 색을 포함하는 객체 : ConcreteFlyweight
좌표값을 포함하는 객체 : UnsharedConcreteFlyweight
폭탄을 생성하는 객체 : FlyweightFactory
나무의 공통되는 속성들을 TreeModel 클래스로 관리
// ConcreteFlyweight - 플라이웨이트 객체는 불변성을 가져야한다. 변경되면 모든 것에 영향을 주기 때문이다.
final class TreeModel {
// 메시, 텍스쳐 총 사이즈
long objSize = 90; // 90MB
String type; // 나무 종류
Object mesh; // 메쉬
Object texture; // 나무 껍질 + 잎사귀 텍스쳐
public TreeModel(String type, Object mesh, Object texture) {
this.type = type;
this.mesh = mesh;
this.texture = texture;
// 나무 객체를 생성하여 메모리에 적재했으니 메모리 사용 크기 증가
Memory.size += this.objSize;
}
}
//UnsahredConcreteFlyweight
class Tree {
// 죄표값과 나무 모델 참조 객체 크기를 합친 사이즈
long objSize = 10; // 10MB
// 위치 변수
double position_x;
double position_y;
// 나무 모델
TreeModel model;
public Tree(TreeModel model, double position_x, double position_y) {
this.model = model;
this.position_x = position_x;
this.position_y = position_y;
// 나무 객체를 생성하였으니 메모리 사용 크기 증가
Memory.size += this.objSize;
}
}
// FlyweightFactory
class TreeModelFactory {
// Flyweight Pool - TreeModel 객체들을 Map으로 등록하여 캐싱
private static final Map<String, TreeModel> cache = new HashMap<>(); // static final 이라 Thread-Safe 함
// static factory method
public static TreeModel getInstance(String key) {
// 만약 캐시 되어 있다면
if(cache.containsKey(key)) {
return cache.get(key); // 그대로 가져와 반환
} else {
// 캐시 되어있지 않으면 나무 모델 객체를 새로 생성하고 반환
TreeModel model = new TreeModel(
key,
new Object(),
new Object()
);
System.out.println("-- 나무 모델 객체 새로 생성 완료 --");
// 캐시에 적재
cache.put(key, model);
return model;
}
}
}