# 플라이웨이트 (Flyweight) 패턴
# 플라이웨이트 패턴이란 무엇인가요?
플라이웨이트 패턴(Flyweight pattern)는 동일하거나 유사한 객체들 사이에 가능한 많은 데이터를 서로 공유하여 사용하도록 하여 메모리 사용량을 최소화하는 소프트웨어 디자인 패턴이다.
- 애플리케이션에서 많은 인스턴스를 만들어 메모리 사용이 많아지게 되면 메모리 부족 현상이 발생한다.
- 따라서 자주 변하지 않는 속성을 모아서 해당 패턴을 적용하기에 적합하다.
- Flyweight
- 공유에 사용할 클래스 (또는 API)
- FlyweightFactory
- Flyweight 인스턴스를 생성 또는 공유 (공장 역할)
- Client
- Flyweight 인스턴스를 필요로 하는 클라이언트
# 어떤 상황에서 사용해야 할까요?
- 공통적인 인스턴스를 많이 생성하는 로직이 포함된 경우
- 자주 변하지 않는 속성을 재사용할 수 있는 경우
public class Character {
private char value;
private String color;
private String fontFamily;
private int fontSize;
public Character(char value, String color, String fontFamily, int fontSize) {
this.value = value;
this.color = color;
this.fontFamily = fontFamily;
this.fontSize = fontSize;
}
}
- 한컴에서 글을 작성할 경우, 각 글자 하나마다 문자, 색상, 폰트종류, 사이즈가 필요하다.
public class Client {
public static void main(String[] args) {
Character c1 = new Character('h', "white", "Nanum", 12);
Character c2 = new Character('e', "white", "Nanum", 12);
Character c3 = new Character('l', "white", "Nanum", 12);
Character c4 = new Character('l', "white", "Nanum", 12);
Character c5 = new Character('o', "white", "Nanum", 12);
}
}
- 글자 하나마다 Character 인스턴스를 생성하게 되는데 이때 폰트 종류와 사이즈는 변경이 적다.
- 자주 변경되지 않는 두 속성을 모아 패턴을 적용시킬 필요가 있다.
# 플라이웨이트 패턴 적용
@Getter
public final class Font {
final String family;
final int size;
public Font(String family, int size) {
this.family = family;
this.size = size;
}
}
@Getter
public class Character {
private char value;
private String color;
private Font font;
public Character(char value, String color, Font font) {
this.value = value;
this.color = color;
this.font = font;
}
}
import java.util.HashMap;
import java.util.Map;
public class FontFactory {
private Map<String, Font> cache = new HashMap<>(); // cache
public Font getFont(String font) {
if (cache.containsKey(font)) {
return cache.get(font);
} else {
String[] split = font.split(":");
Font newFont = new Font(split[0], Integer.parseInt(split[1]));
cache.put(font, newFont);
return newFont;
}
}
}
- FontFactory의 getFont() 메소드를 통해 Font 생성을 하게 되면, HashMap에 데이터가 있는지 먼저 검사하게 된다
- 기존에 저장해둔 Font 인스턴스가 있다면, 새로 생성하지 않고 기존 인스턴스를 반환해준다.
public class Client {
public static void main(String[] args) {
FontFactory fontFactory = new FontFactory();
Character c1 = new Character('h', "white", fontFactory.getFont("nanum:12"));
Character c2 = new Character('e', "white", fontFactory.getFont("nanum:12"));
Character c3 = new Character('l', "white", fontFactory.getFont("nanum:12"));
}
}
# 플라이웨이트 패턴의 장단점
장점
- 애플리케이션에서 사용하는 메모리를 줄일 수 있다.
단점
- 코드의 복잡도가 증가한다
# 싱글톤 패턴과 무엇이 다른가요?
- 싱글톤 패턴은 클래스 자체가 오직 1개의 인스턴스만 허용한다.
- 플라이웨이트 패턴은 싱글톤이 아닌 클래스를 팩토리에서 제어한다.
인스턴스 생성의 제한을 어디서 제어하느냐에 차이이다.
# 플라이웨이트 패턴의 예시는?
- Integer
Integer i1 = Integer.valueOf(10);
Integer i2=Integer.valueOf(10);
System.out.println(i1 == i2); // true
- 근데 자주 사용되는 값들에 대해서만 캐싱을 하고, 아닌 것은 캐싱을 하지 않는다고 한다...
# 참고자료
- https://ko.wikipedia.org/wiki/%ED%94%8C%EB%9D%BC%EC%9D%B4%EC%9B%A8%EC%9D%B4%ED%8A%B8_%ED%8C%A8%ED%84%B4
- https://dev-youngjun.tistory.com/217