apple/DesignPattern, Architecture

Swift 디자인패턴 FlyWeight Pattern (플라이웨이트 패턴)

lgvv 2022. 6. 9. 21:16

Swift 디자인패턴 FlyWeight Pattern (플라이웨이트)

 
플라이웨이트 패턴은 메모리 사용량과 처리 과정을 최소화하기 위한 구조 패턴.
 

히스토리

  • 2022-06-09: 디자인 패턴 스터디 정리
  • 2024-11-26: 포스팅 글 재정리 및 조금 더 실용적인 예제 코드로 변경

 

Flyweight Pattern

 

FlyWeight Pattern

메모리를 효율적으로 사용하는 디자인 패턴으로, 공유 가능한 상태(공통 속성)를 분리하여 객체 생성 비용을 줄이는 방법을 제공

  • 대량의 객체를 생성해야 할 때 유용
  • 특히 반복적인 데이터를 다루는 경우 메모리 사용량을 크게 줄일 수 있음
  • 캐시를 구현하는데도 사용할 수 있음

플라이웨이트 패턴은 일반적으로 3가지 개념으로 구성됨

  • Intrinsic State: 공유 가능한 상태로 객체 간 공통된 데이터
  • Extrinsic State: 공유되지 않으며, 각 객체에 개별된 데이터
  • Flyweight Factory: 플라이웨이트 객체를 생성하고 관리하여 중복 생성을 방지

플라이웨이트 패턴 적용을 고려할 수 있는 상황

  • 메모리 사용량을 줄이는 것이 중요한 경우
  • 동일하거나 유사한 객체를 대량으로 생성할 때
  • 객체의 공통 상태와 개별 상태를 명확히 구분할 수 있을 때

활용 예시

  • iOS에서 폰트 객체를 재사용하여 메모리를 절약.
  • 캐싱을 활용한 이미지 및 리스트 캐시 관리 (NSCache 또는 커스텀 캐시 구현)

 

코드 예제

캐릭터 객체를 만들고 공유하는 상태와 공유하지 않는 상태를 객체를 공유

class Character {
    // MARK: - Intrinsic State (공유 상태)
    let font: String
    let color: String

    init(font: String, color: String) {
        self.font = font
        self.color = color
    }

    func display(with text: String, at position: CGPoint) {
        print("Displaying '\(text)' at \(position) using font: \(font), color: \(color)")
    }
}

class CharacterFactory {
    private var characters: [String: Character] = [:]

    func getCharacter(font: String, color: String) -> Character {
        let key = "\(font)-\(color)"
        if let character = characters[key] {
            return character
        } else {
            let newCharacter = Character(font: font, color: color)
            characters[key] = newCharacter
            return newCharacter
        }
    }
}


private struct ContentView: View {
    var body: some View {
        Button("Execute") {
            let factory = CharacterFactory()

            let redArial = factory.getCharacter(font: "Arial", color: "Red")
            redArial.display(with: "Hello", at: CGPoint(x: 10, y: 20))

            let blueArial = factory.getCharacter(font: "Arial", color: "Blue")
            blueArial.display(with: "World", at: CGPoint(x: 30, y: 40))

            let anotherRedArial = factory.getCharacter(font: "Arial", color: "Red")
            print("redArial === anotherRedArial: ", redArial === anotherRedArial) // true
            print("redArial === blueArial: ", redArial === blueArial) // false 
        }
    }
}

#Preview {
    ContentView()
}

 

위 코드 결과



정리

주요 이점

  • 메모리 절약: 중복 객체 생성 방지
  • 성능 개선: 객체 생성과 관리 효율성 증가

주의점

  • 코드 복잡성 증가할 수 있음
  • 공유 상태랑 개별 상태를 정확히 구분해야 패턴의 효과를 발휘할 수 있음

 




(참고)
https://www.raywenderlich.com/books/design-patterns-by-tutorials/v3.0/chapters/18-flyweight-pattern

Design Patterns by Tutorials, Chapter 18: Flyweight Pattern

This creational design pattern minimizes memory usage and processing. It also provides objects that all share the same underlying data, thus saving memory. Learn about flyweight objects and static methods to return them.

www.kodeco.com:443

https://refactoring.guru/ko/design-patterns/flyweight

플라이웨이트 패턴

/ 디자인 패턴들 / 구조 패턴 플라이웨이트 패턴 다음 이름으로도 불립니다: 캐시, Flyweight 의도 플라이웨이트는 각 객체에 모든 데이터를 유지하는 대신 여러 객체들 간에 상태의 공통 부분들을

refactoring.guru