플라이웨이트(Flyweight) 패턴
객체를 가볍게 만들어 메모리 사용을 줄이는 패턴이다.
자주 변하는 속성(외적인 속성, extrinsic)과 변하지 않는 속성(내적인 속성, 본질적인 속성, instrinsit)을 분리하고
내적인 속성을 재사용하여 메모리 사용을 줄일 수 있다.
플라이웨이트(Flyweight) 패턴 before
@AllArgsConstructor
public class Character {
private char value;
private String color;
private String fontFamily;
private int fontSize;
}
Character 클래스는 문자의 값(value), 문자의 색깔(color), 폰트(fontFamily), 폰트 사이즈(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를 생성하는 클라이언트 코드이다.
보통 폰트와 폰트 사이즈는 대부분 정해진 규격만 사용한다.
ex) 제목 폰트 & 사이즈 20 / 내용 폰트 & 사이즈 10
현재 클라이언트 코드는 이런 변하지 않는 속성도 Character를 생성할 때 같이 만들어주고 있다.
플라이 웨이트 패턴을 사용하여 이런 변하지 않는 속성을 재사용할 수 있게 만들어 보겠다.
플라이웨이트(Flyweight) 패턴 after
Font 클래스
@RequiredArgsConstructor @Getter
public class Font {
private final String family;
private final int size;
}
기존 Character 클래스에서 재사용성이 높은 필드(내적인 속성)인 fontFamily & fontSize를 필드로 가지는 클래스이다.
재사용하는 객체인 Font는 불변 객체여야 한다.
만약 재사용하는 객체가 변경이 가능하면 해당 객체를 사용하는 모든 곳에서 변경이 일어난다.
그러니 final 키워드를 모든 필드에 붙여서 객체를 변경 불가능하게 만들자
Character 클래스
@AllArgsConstructor
public class Character {
private char value;
private String color;
private Font font;
}
fontFamily, fontSize → Font(클래스)
FontFactory
public class FontFactory {
private Map<String, Font> cache = new HashMap<>();
public Font getFont(String font){
if(cache.containsKey(font)){
return cache.get(font);
}
String [] split = font.split(":");
Font newFont = new Font(split[0], Integer.parseInt(split[1]));
cache.put(font, newFont);
return newFont;
}
}
FontFactory는 cache(HashMap)에 폰트가 있으면 이미 생성해둔 폰트를 반환하고 없으면
새로 Font를 생성해서 반환한다. 이때 새로 생성한 Font를 cache에 저장한다.
클라이언트 코드
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"));
}
}
처음 getFont("nanum:12")를 호출했을 때 font 생성이 되고 그 이후로는 cache에서 가져온다.
즉 fontFamily fontSize 2개의 자주 사용되는 속성을 재사용하게 되었다.
이렇듯 flyweight 패턴은 객체를 재사용함으로써 성능을 올려주는 패턴이다.
플라이웨이트(Flyweight) 패턴 정리
객체를 가볍게 만들어 메모리 사용을 줄이는 패턴
장점
애플리케이션에서 사용하는 메모리를 줄일 수 있다
단점
코드의 복잡도가 증가한다
플라이웨이트(Flyweight) 패턴 적용 사례
Integer.valueOf API
public class IntegerExample {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(10);
Integer i2 = Integer.valueOf(10);
System.out.println(i1 == i2); // true
Integer i3 = Integer.valueOf(10000);
Integer i4 = Integer.valueOf(10000);
System.out.println(i3 == i4); // false
}
}
캐시를 제공한다.
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
@IntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
-128 ~ 127 범위까지의 범위에 있는 값을 캐시하며, 이 범위 밖의 다른 값도 캐시할 수 있다.
참고자료
'Computer Sience > Desgin Pattern' 카테고리의 다른 글
[Design Pattern] 책임 연쇄(Chain of Responsibility) 패턴 (1) | 2024.10.31 |
---|---|
[Design Pattern] 프록시(Proxy) 패턴 + 다이나믹 프록시 (0) | 2024.10.30 |
[Design Pattern] 퍼사드(Facade) 패턴 (1) | 2024.10.28 |
[Design Pattern] 데코레이터 (Decorator) 패턴 (0) | 2024.10.28 |
[Design Pattern] 컴포짓 (Composite) 패턴 (1) | 2024.10.24 |