Exist Technote

[Python] Flyweight Pattern (플라이웨이트) 본문

Design Pattern/Structural

[Python] Flyweight Pattern (플라이웨이트)

by_Exist 2020. 10. 7. 16:03

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

Flyweight Pattern이란?

  • 크기가 작은 객체가 여러 개(엄~청...) 있을 때 공유를 통해 이들을 효율적으로 지원하는 패턴.

예제

import weakref


class Card:

    # 매핑형, 참조 카운트를 증가시키지 않아 객체가 GC에 의해 제거되는 것을 막지 못한다.
    _pool = weakref.WeakValueDictionary()

    def __new__(cls, value, suit):
        obj = cls._pool.get(value + suit)
        if obj is None:
            obj = object.__new__(Card)
            obj.value, obj.suit = value, suit
            cls._pool[value + suit] = obj
        return obj

    def __repr__(self):
        return "<Card: {}{}>".format(self.value, self.suit)


if __name__ == "__main__":

    c1 = Card('10', 'd')
    print([card for card in Card._pool.items()])

    del c1
    print([card for card in Card._pool.items()])    # GC test

    c2 = Card('9', 'h')
    c3 = Card('9', 'h')
    c4 = Card('9', 'h')

    c4.new_attr = "test"

    print(c2 is c3 is c4)    # all same instance
    print(c3.__dict__)

여담

  • weakref를 통해 참조 카운트를 증가시키지 않는 Object pool 패턴을 사용하여 설계된 패턴이다.
  • 생성 패턴의 Multiton 패턴과 매우 유사해보인다.
    • 멀티톤은 조건에 맞는 동일 인스턴스를 요구하는 생성 패턴이지만
    • 플라이웨이트 패턴은 객체 공유를 통해 자원을 아끼는 구조 패턴이다.
  • 워드 프로세스의 모든 문자 하나하나가 인스턴스를 생성한다면 비효율적일 것이다.
    • 각 문자에 해당하는 인스턴스를 하나만 생성한다면(Multiton) 메모리를 효율적으로 아낄 수 있을 것이다.
    • 하지만, 만약 문장 일부분에만 폰트, 색상을 적용할 수 있다고 해보자.
    • A + 폰트1 + red = A1 ... 멀티톤으로 구현하기에는 인스턴스의 수가 많아진다.
    • A + choice(폰트) + choice(컬러) = font_color_A ... 공유하는 방식으로 구성하는 것이 효율적일 것이다.
  • weakref를 보니, 파이썬의 기본 라이브러리를 배워야겠다고 느낀다.
Comments