오늘은 Flyweight 패턴에 대해 알아보겠습니다.
제가 공부하면서 느낀 점은 캐싱과 비슷하다였습니다. 필요한 인스턴스를 만들어 저장해 재사용하는 느낌이었습니다.
Flyweight 패턴은 자주 변하는 속성과 변하지 않은 속성을 분리하고 재사용하여 메모리 사용을 줄일 수 있습니다.
(변하지 않는 속성을 재사용합니다.)
여기서 주의할 점은 변하는 속성과 변하지 않는 속성은 개발자 주관적이기 때문에 잘 분석하고 선택해야 합니다.
Flyweight을 설계할 때 주의할 점은 Flyweight 객체는 immutable 해야 합니다.
우리가 만약 메모장을 앱을 만든다면 무수히 많은 Text 객체를 만들어야 할 수 있습니다. Text객체에는 text, font, fontColor, size 프로퍼티를 가지고 있습니다.
class Text {
var text: String
var font: String
var fontColor: String
var size: Int
init(text: String, font: String, fontColor: String, size: Int) {
self.text = text
self.font = font
self.fontColor = fontColor
self.size = size
}
}
class App {
func makeText() {
let text1 = Text(text: "안녕", font: "유성매직", fontColor: "black", size: 13)
let text2 = Text(text: "hello", font: "궁서체", fontColor: "black", size: 15)
}
}
만약 동일한 font와 size를 가지는 text를 만들고 싶어도 재사용이 불가능해 하나하나 인스턴스를 생성해야 합니다.
class Text {
var text: String
var fontColor: String
var flyweight: Flyweight
init(text: String, fontColor: String, flyweight: Flyweight) {
self.text = text
self.fontColor = fontColor
self.flyweight = flyweight
}
}
final class Flyweight {
private var font: String
private var size: Int
init(font: String, size: Int) {
self.font = font
self.size = size
}
func getFont() -> String {
return self.font
}
func getFontSize() -> Int {
return self.size
}
}
Flyweight는 불변해야 하기 때문에 final 키워드를 이용해 상속을 못 하게 막아주고 각각 프로퍼티에는 Private 처리해 주었습니다.
class FlyweightFactory {
var cache = [String: Flyweight]()
func getFlyweight(name: String) -> Flyweight {
let font = name.split(separator: ":").map { String($0) }
if let flyweight = cache[font[0]] {
return flyweight
} else {
let newFlyweight = Flyweight(font: name, size: Int(font[1])!)
cache.updateValue(newFlyweight, forKey: font[0])
return newFlyweight
}
}
}
생성한 Flyweight를 재사용하기 위한 객체입니다.
현재 저는 Dictionary 형태로 구현했지만 구현 방법은 자유입니다. 만약 더 이상 사용하지 않는 Flyweight 객체를 제거하는 방법도 고려할 수 있을 것 같습니다.
class MyApp {
private let flyweightFactory: FlyweightFactory
init(flyweightFactory: FlyweightFactory) {
self.flyweightFactory = flyweightFactory
}
func makeText() {
let text1 = Text(text: "안녕", fontColor: "black", flyweight: flyweightFactory.getFlyweight(name: "유성매직:13"))
let text2 = Text(text: "hello", fontColor: "white", flyweight: flyweightFactory.getFlyweight(name: "궁서체:13"))
let text3 = Text(text: "hi", fontColor: "red", flyweight: flyweightFactory.getFlyweight(name: "유성매직:13"))
}
}
text3 같은 경우 다른 객체를 생성하지 않고 Factory에 저장된 객체를 재사용합니다.
장점
1. App에서 사용하는 메모리를 줄일 수 있습니다.
단점
1. 코드가 복잡합니다.
해당 글은 인프런의 코딩으로 학습하는 GoF 디자인 패턴 강의를 참고해 작성했습니다.
⭐️ 부족하거나 잘못된 부분이 있다면 댓글은 언제나 환영입니다!! ⭐️