공유될 수 있는것과 공유될 수 없는 것을 구분지어 공유될 수 있는 자원을 가지는 객체를 하나만 생성해 전체 프로그램의 메모리 사용량을 줄일 수 있는 패턴
1. 총게임의 총알을 나타내는 Bullet클래스가 있다
class Bullet {
private String type;
private int damage;
private String position;
public Bullet(String type, int damage, String position) {
this.type = type;
this.damage = damage;
this.position = position;
}
}
2. 게임중 거의 동시에 1000발의 총알을 쏜다고 할 때 1000개의 총알을 생성해야 한다
public class Game {
public static void main(String[] args) {
Bullet[] bullets = new Bullet[1000];
for (int i = 0; i < bullets.length; i++) {
bullets[i] = new Bullet("Standard Bullet", 50, "Position " + i);
}
}
}
위 상황에서 총알은 type, damage, position이라는 변수를 가지고 있지만 실제 이미지를 나타내는 image 데이터는 용량이 다른 변수에 비해 용량이 클 것이다. 이런 총알을 1000개가 존재한다면 이미지가 100KB라고 해도 100,000KB=약 100MB이고 더 많아진다면 메모리를 많이 잡아먹을 것이다.
총알의 개별속성인 position을 제외하고 공통부분으로 묶을 수는 없을까?
1. Bullet
class Bullet {
private String type;
private int damage;
public Bullet(String type, int damage) {
this.type = type;
this.damage = damage;
}
}
플라이웨이트 패턴의 ConcreteFlyweight에 해당하는 부분으로 총알의 공통 속성인 type과 damage를 가지고 있다.
2. BulletContext
class BulletContext {
private Bullet bullet;
private String position;
public BulletContext(Bullet bullet, String position) {
this.bullet = bullet;
this.position = position;
}
}
플라이웨이트 패턴의 UnsharedConcreteFlyweight에 해당하는 부분으로 날아가는 총알의 공유할 수 없는 속성인 position을 가지고 있고 공통 속성을 저장한 Bullet 클래스를 가지고 있다.
3. BulletFactory
class BulletFactory {
private Map<String, Bullet> bulletPool = new HashMap<>();
public Bullet getBullet(String type, int damage) {
String key = type + damage;
if (!bulletPool.containsKey(key)) {
bulletPool.put(key, new Bullet(type, damage));
}
return bulletPool.get(key);
}
}
ConcreteFlyweight를 생성하는 팩토리 클래스로 Bullet 인스턴스를 하나만 생성하도록 조절한다. 위 클래스는 HashMap을 사용하는 방식이며 List를 사용하는 방법도 사용가능 하지만 Index에 해당하는 값을 넘겨주어야 한다.
4. Game
public class Game {
public static void main(String[] args) {
BulletFactory factory = new BulletFactory();
BulletContext[] bulletContexts = new BulletContext[1000];
for (int i = 0; i < bulletContexts.length; i++) {
Bullet bullet = factory.getBullet("Standard Bullet", 50);
bulletContexts[i] = new BulletContext(bullet, "Position " + i);
}
}
}
문제상황과 같이 1000개의 총알을 생성하지만 필요한 메모리는 크게 줄을 것이다. 이미지파일의 크기를 100KB라고 한다면 패턴을 적용하면 1000개의 총알에 대한 이미지파일의 용량은 하나의 인스턴스만 생성되기 때문에 100KB가 된다.
플라이웨이트 패턴을 적용했을 때 가장 큰 이점은 역시 필요 메모리 축소
이다. 그렇다면, 필요 메모리가 많은 상황
에 사용하면 된다.
공유될 수 없는 상태
를 찾아낼 수 있는가?Extrinsic state가 많을수록 플라이웨이트 패턴의 효과가 미미하다.
Reference counting, 유일성 보장을 위한 Singleton pattern을 적용