있을 유, 참 진

[디자인 패턴] 플라이웨이트 패턴:: 메모리 가볍게 사용하기 본문

디자인패턴

[디자인 패턴] 플라이웨이트 패턴:: 메모리 가볍게 사용하기

U_ma 2023. 4. 4. 22:12
플라이웨이트 패턴 설명
   - 장점
   - 단점
문제점 분석
   - 예시 코드 설명
      1. Character
      2. Client
플라이웨이트 패턴 적용
   - instrinsit 속성
      1. Font
      2. FontFactory
   - extrinsit 속성 + 구현
      1. Character
      2. Client

플라이웨이트 패턴 설명

💡 복싱이나 격투기에서는 가장 가벼운 체급을 플라이급이라고 칭한다. 구조 패턴 중 하나로 메모리 사용을 줄이는 패턴. 자주 변하는 속성(extrinsit)과 변하지 않는 속성(instrinsit)을 분리, 재사용해 메모리 사용을 줄인다.
플라이웨이트 패턴은 아래와 같을 때 큰 효과를 볼 수 있다.
1. 애플리케이션에 의해 생성되는 객체가 많아질 때
2. 생성된 객체가 많아져 저장 비용이 높아질 때
3. 애플리케이션에서 객체의 정체성에 의존되지 않을 때, 플라이급 객체는 공유될 수 있어야 한다.

플라이웨이트 패턴

장점

애플리케이션 사용 메모리 절약

단점

코드의 복잡도 증가

문제점 분석

💡 아래 예시와 같이 한 글자마다 특성을 주는 객체가 존재한다 했을 시 객체를 하나씩 살리는 것은 데이터의 낭비가 될 수 있다. 그렇다면 아래에 자주 변하지 않는 특성인 'Nanum', '12'를 활용해 메모리를 아낄 수 있는 방법이 없을까?

예시 코드 설명

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

public class Client {
    public static void main(String[] args) {
        //오 이런.. 'Nanum', 12가 중복으로 사용되고 있다.
        Character character1 = new Character('H', "white", "Nanum", 12);
        Character character2 = new Character('e', "white", "Nanum", 12);
        Character character3 = new Character('l', "white", "Nanum", 12);
        Character character4 = new Character('l', "white", "Nanum", 12);
        Character character5 = new Character('o', "white", "Nanum", 12);
    }
}

플라이웨이트 패턴 적용

instrinsit 속성

💡 앞에서 언급한 것처럼, 폰트 패밀리와 사이즈는 자주 변하지 않는 속성으로 관리될 것이다. 그렇기에 'Font' 객체로 묶이며 'FontFactory'를 생성해 준다.

Font

public 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;
    }
}

FontFactory

💡 캐시가 존재하면 해당하는 캐시에서 꺼내서 사용, 그렇지 않으면 해당 키를 사용하며 캐시로 저장하는 곳
public class FontFactory {
    //캐쉬를 저장하는 곳 자주 변하지 않는 Font의 정보를 저장한다.
    private static final Map<String, Font> cache = new HashMap<>();

    public static 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;
        }
    }
}

extrinsit 속성 + 구현

Character

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;
    }

}

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"));
    }
}
Comments