개발자로 후회없는 삶 살기
디자인 패턴 PART.플라이웨이트 패턴 본문
서론
※ 이 포스트는 다음 강의의 학습이 목표임을 밝힙니다.
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard
본론
- 패턴 소개
가벼운이라는 뜻으로 복싱 체급중에 가벼운 체급을 플라이 웨이트라고 합니다. 많은 객체를 만드는 어플에서 결국 OOM이 발생할 수 있는데 그때 사용할 수 있는 패턴입니다. 자주 변하지 않는 속성을 따로 모아서 재사용하는 방법입니다.
- 코드
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 객체가 있고 val, 색깔, 폰트를 가지고 있습니다. 이 문자 객체를 가지고 편집기에 글을 많이 쓰면 많이 쓸 수록 객체가 많아집니다. 그 만큼 이 객체의 메모리가 최적화되지 않으면 편집기의 성능에 영향을 줄 것입니다. 여기에 플라이웨이트 패턴을 적용합니다.
=> 구조
객체의 데이터 중에 자주 변하는 것과 변하지 않는 것을 분리하여 재사용합니다. 변하지 않는 것을 모아 놓은 것이 플라이웨이트고 플라이웨이트를 클라이언트가 팩토리를 통해서 가져다 씁니다. 팩토리에서는 플라이웨이트를 캐싱해서 클라이언트가 가져다 쓸 수 있게끔해서 메모리 사용을 극도로 줄입니다.
- 패턴 적용
캐릭터의 속성 중에서 자주 바뀌지 않는 것을 플라이웨이트에 넣습니다. 이건 주관적인 것으로 여기서는 폰트 패밀리와 사이즈라고 보고 이 둘을 묶은 것을 플라이웨이트라고 할 것입니다.
-> 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;
}
}
플라이웨이트에 해당하는 폰트 클래스르 만듭니다. 여기에 패밀리와 사이즈를 정의합니다. 이때 주의할 것은 플라이웨이트에 해당하는 속성은 emmutable해야합니다. 따라서 final 키워드를 씁니다. 그리고 상속을 막아야 해서 final 클래스로 만듭니다.
public class Character {
String color;
private char value;
Font font;
public Character(String color, char value, Font font) {
this.color = color;
this.value = value;
this.font = font;
}
}
그리고 변하는 속성을 가지고 있는 캐릭터를 만듭니다. val과 color를 가지고 있고 여기서 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;
}
}
}
플라이웨이트를 캐싱하고 접근할 수 있어야 합니다. Map으로 캐시를 구현할 것입니다. getFont로 플라이웨이트를 가져오는 메서드를 만듭니다.
-> 클라이언트
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"));
}
이제 캐릭터를 만들 때 value, color는 그대로 하는데 폰트는 팩토리에서 가져옵니다. 이렇게 되면 이 폰트 객체들은 모두 공유한 것이라서 메모리를 덜 쓰게 됩니다.
- 장, 단점
어플에서 사용하는 메모리를 줄일 수 있습니다. 기존에는 캐릭터가 모든 데이터를 가지고 있어서 힙에 메모리를 계속 먹을 것인데 플라이웨이트를 하면 하나의 객체를 사용해서 메모리를 아낍니다. 또한 팩토리에서 캐싱을 하기 때문에 항상 동일한 객체를 사용합니다.
'[백엔드] > [Java | 학습기록]' 카테고리의 다른 글
코드 조작 PART.바이트 코드 조작 (0) | 2023.09.30 |
---|---|
디자인 패턴 PART.프록시 패턴 (0) | 2023.08.21 |
디자인 패턴 PART.퍼사드 패턴 (0) | 2023.08.21 |
디자인 패턴 PART.데코레이터 패턴 (0) | 2023.08.20 |
디자인 패턴 PART.컴포짓 패턴 (0) | 2023.08.20 |