반응형
플라이웨이턴 패턴 (Flyweight Pattern) 란?
- 여러 클래스의 인스턴스 한 개만 가지고 여러 개의 "가상 인스턴스"를 제공하고 싶을 때 사용하는 패턴이다.
- 인스턴스를 가능한 대로 공유시켜 슬데없이 new 연산자를 통한 메모리 낭비를 줄이는 방식이다.
- 자주 변하는 속성(외적인 속성, extrinsit)과 변하지 않는 속성(내적인 속성, intrinsit)을 분리하고 재사용하여 메모리 사용을 줄인다
Character 클래스
- 글자 하나를 표현한 도메인
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;
}
}
Client
- 편집기에 글을 입력하는 클라이언트
- 글자 하나마다 Character 인스턴스를 생성한다.
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);
}
}
편집기에 글을 쓰면 한글자 한글자 모두 new 생성자를 통해 객체를 생성하게 되는데, 메모리를 아끼기 위해 자주 변하는 속성(공유불가), 자주 변하지 않는 속성(공유)을 분류해보자.
- 문자와 색 : 자주 변하는 속성
- 색은 ENUM 타입으로 선언해주어도 좋을 것 같다.
- 글자 폰트와 크기 : 자주 변하지 않는 속성
Font 라는 클래스(Flyweight)로 만들어서 개선해보자.
플라이웨이트 패턴 적용
Character 인스턴스가 모든 데이터를 따로 저장하지 않고, 공유할 수 있는 부분을 공유해서 메모리를 아껴보자.
자주 변하지 않아서 공유할 수 있는 속성으로 분류했던 글자 폰트와 글자 크기 속성을 Font 클래스로 선언했다.
Font
public final class Font {
final String family;
final int size;
public Font(String family, int size) {
this.family = family;
this.size = size;
}
public String getFamily() {
return family;
}
public int getSize() {
return size;
}
}
- 공유하는 객체이기 때문에 불변으로 선언 (final)
- 생성자로만 선언 + getter 접근
Character
Font를 field로 갖도록 수정했다.
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;
}
}
FontFactory
Font 생성을 관리해주는 팩토리는 다음과 같다.
public class FontFactory {
private Map<String, Font> cache = new HashMap<>();
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 인스턴스가 있다면, 새로 생성하지 않고 기존 인스턴스를 반환해준다.
Client
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"));
Character c4 = new Character('l',"white", fontFactory.getFont("nanum:12"));
Character c5 = new Character('o',"white", fontFactory.getFont("nanum:12"));
}
}
장점
- 많은 객체를 만들때 성능을 향상시킬수 있다
- 많은 객체를 만들때 메모리를 줄일수 있다
단점
- 특정 인스턴스를 다르게 처리하는게 힘들다
참고
'디자인패턴' 카테고리의 다른 글
템플릿 메소드 패턴(Template Method Pattern) (1) | 2022.09.25 |
---|---|
전략패턴(Strategy Pattern) (1) | 2022.09.20 |
퍼사드 패턴(Facade Pattern) (0) | 2022.08.14 |
데코레이터(Decorator) 패턴 (0) | 2022.08.04 |
컴포짓(composite) 패턴 (0) | 2022.07.30 |