apple/DesignPattern & Architecture

[Swift] FlyWeight Pattern

lgvv 2022. 6. 9. 21:16

FlyWeight Pattern

✅ FlyWeight Pattern

 

아래의 문서를 구입하여 영어 문서를 번역하고 이해한 것을 바탕으로 글을 작성하고 있습니다.

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.raywenderlich.com

 

FlyWeight 패턴은 메모리사용량과 처리를 최소화하는 구조적 디자인 패턴입니다.

FlyWeight

 

Flyweight 패턴은 모든객체가 기본 데이터를 공유함으로써 메모리를 절약하게 된다. 하지만, 데이터 공유를 하기에 immutable(변경이 불가능)합니다. 

 

플라이웨이트 패턴에는 flyweights라고 불리는 객체와 그리고 그들을 반환하는 정적 메소드가 있습니다.

 

이 말이 익숙하게 들리시나요? 당연히 그래야 합니다!! 플라이웨이트 패턴은 싱글톤 패턴의 변형이기 때문입니다. 플라이웨이트 패턴에서는 일반적으로 동일한 클래스의 서로 다른 객체가 여러개 있습니다. 우리가 이제 볼 예제로, 한 가지 예가 색의 사용입니다. 우리는 지금 빨간색, 녹색 등이 필요합니다. 이러한 각 색상은 동일한 기본 데이터를 공유하는 단일 인스턴스입니다.

 

When should you use it?

 

싱글톤을 사용할 장소에는 플라이웨이트를 사용하지만 구성이 다른 여러 공유 인스턴스가 필요합니다. 생성해야 하는 리소스가 많은 개체가 있고 생성 프로세스 비용을 최소화할 수 없는 경우 가장 좋은 방법은 개체를 한 번만 생성하고 대신 전달하는 것입니다.

 

( * 개인의견: 싱글톤과 아주 닮았지만, 팩토리 메소드 패턴과 섞어서 사용하는 것이다. )

장점: 메모리를 절약할 수 있음.

단점: 런타임 시 마다 만들기 때문에 똑같은 객체를 만들면 느려질 수 있다.

 

Playground example

여기서는 UIKit을 사용하여 간단히 테스트 해봅시다.

import UIKit

let red = UIColor.red
let red2 = UIColor.red
print(red === red2)

위의 코드에서 print이의 결과가 true이므로 즉, UIColor가 플라이웨이트 패턴을 사용한다는 것을 증명합니다. ===문을 통해서 색상을 비교하면 변수의 메모리 주소가 동일하다는 것을 알 수 있습니다. 즉, .red는 플라이웨이트이며 한 번만 인스턴스화 됩니다.

 

let color = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
let color2 = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
print(color === color2)

 

이번에는 콘솔에 결과가 false로 기록됩니다. 사용자 지정 UI색상 객체는 플라이웨이트가 아닙니다. 이 메소드는 빨간색, 녹색, 파란색을 사용하고 호출될 때마다 새 UI 색상을 반환합니다.

 

UIColor가 값을 확인하여 색상이 이미 생성되었는지 확인한 경우 대신 플라이웨이트 인스턴스를 반환할 수 있습니다. UIColor extension을 통해서 플라이웨이트를 반환합니다. 

extension UIColor {
  
  // 1
  public static var colorStore: [String: UIColor] = [:]
  
  // 2
  public class func rgba(_ red: CGFloat,
                         _ green: CGFloat,
                         _ blue: CGFloat,
                         _ alpha: CGFloat) -> UIColor {
    
    let key = "\(red)\(green)\(blue)\(alpha)"
    if let color = colorStore[key] {
      return color
    }
    
    // 3
    let color = UIColor(red: red,
                        green: green,
                        blue: blue,
                        alpha: alpha)
    colorStore[key] = color
    return color
  }
}

1. 딕셔너리를 생성하고, RGBA의 값을 저장합니다.

2. UIColor 방법처럼 빨강, 파랑, 알파를 key로 사용합니다. RGB 값을 키라는 문자열에 저장합니다. 해당 키를 가진 색상이 colorStore에 이미 있는 경우 새 키를 만드는 대신 해당 키를 사용하십시오.

3. 키가 아직 colorStore에 없는 경우 UI 색상을 생성하고 키와 함께 저장합니다.

 

let flyColor = UIColor.rgba(1, 0, 0, 1)
let flyColor2 = UIColor.rgba(1, 0, 0, 1)
print(flyColor === flyColor2)

이제 true를 반환하는 것을 확인할 수 있습니다.

 

 

What should you be careful about?

 

플라이웨이트를 만들 때, 플라이웨이트 메모리가 얼마나 커지는지 주의하세요. 위의 colorStore에서와 같이 여러 개의 플라이웨이트를 저장하는 경우 동일한 색상에 대한 메모리 사용을 최소화하지만, 플라이웨이트 스토어에서 메모리를 사용할 수 있습니다.

 

이를 완화하기 위해서는 메모리 양에 대한 경계를 설정하거나, 메모리 경고에 등록하고 메모리에서 일부 플라이웨이트를 제거하여 등록합니다. LRU 캐시를 사용하여 이를 처리할 수 있습니다. 

 

또한 플라이웨이트 shared 인스턴스는 구조가 아닌 클래스여야 합니다. struct는 copy하기 때문에, ref 형식으로 작성한 이점을 얻을 수 없습니다.

Copying

 

Tutorial Project

플라이웨이트 패턴은 팩토리 메소드 패턴과 같이 사용하면 좋다. 해당 예제는 참고에 넣어두었다.

 

https://github.com/lgvv/DesignPattern/tree/main/flyweight-pattern

 

GitHub - lgvv/DesignPattern: ✨ 디자인 패턴을 공부합니다!

✨ 디자인 패턴을 공부합니다! Contribute to lgvv/DesignPattern development by creating an account on GitHub.

github.com

 

Key points

플라이웨이트 패턴에 대해서 배웠습니다.

 - 플라이웨이트 패턴은 메모리 사용량과 처리를 최소화합니다.

 - 이 패턴에는 플라이웨이트라고 하는 객체와 이를 반환하는 정적 메소드가 있습니다. 싱글톤 패턴의 변형으로 볼 수 있습니다.

 - 플라이웨이트를 생성할 때 플라이웨이트 메모리 크기에 주의하세요. 

 - 플라이웨이트를 생성할 때 플라이웨이트 메모리의 크기에 주의하세요! 여러 플라이우에트를 저장하는 경우 플라이웨이트 저장소에서 너무 많은 메모를 사용할 수 있습니다.

 - 플라이트웨이트의 예로는 이미지와 같은 객체를 캐싱하거나, 빠른 액세스를 위해 메모리에 저장된 객체 풀을 유지하는 것이 있습니다.

 

 

(참고) 

https://icksw.tistory.com/247?category=944177 

 

[Swift 디자인 패턴] Flyweight Pattern (플라이웨이트) - 디자인 패턴 공부 12

안녕하세요 Pingu입니다.🐧 지난 글에서는 구조 패턴 중 Facade Pattern(퍼사드)에 대해 알아봤는데요, 이번 글에서는 계속해서 구조 패턴 중 하나인 Flyweight Pattern(플라이 웨이트)에 대해 알아보도록

icksw.tistory.com