파이썬에서 디자인 패턴 'Flyweight' 배우기

GoF의 디자인 패턴을 학습하는 소재로서, 서적 「 증보 개정판 Java 언어로 배우는 디자인 패턴 입문 」가 참고가 되는 것 같네요. 다만, 다루어지고 있는 실례는, JAVA 베이스이기 때문에, 자신의 이해를 깊게 하기 위해서도, Python에서 동등의 프랙티스에 도전해 보았습니다.

■ Flyweight (플라이 웨이트 패턴)



Flyweight 패턴 (플라이 웨이트 패턴)은 GoF에 의해 정의 된 디자인 패턴 중 하나입니다. 동등한 인스턴스를 별도의 위치에서 사용할 때 하나의 인스턴스를 재사용하여 프로그램을 자원 절약하는 것을 목표로합니다.

UML class and sequence diagram





UML 클래스 diagram




(이상 위키피디아(Wikipedia)에서 인용)

□ 비망록



flyweight라고 하는 것은, 「플라이급」으로, 권투에서 가장 체중이 가벼운 계급을 나타내는 것이며, 이 디자인 패턴에서는, 오브젝트를 「가볍게」하기 위한 것이라고 합니다.Flyweight 패턴으로 사용하고 있는 기법은, 「인스턴스를 가능한 한 공유시켜, 쓸데없이 new 하지 않는다」라고 하는 것으로, 인스턴스가 필요할 때, 언제나 new 하는 것이 아니라, 벌써 만들고 있는 인스턴스를 이용할 수 있다 그렇다면 그것을 공유하고 사용하는 것 같습니다.
직관적으로, 디자인 패턴 "Singleton" 의 응용이라고 느끼네요.

■ "Flyweight" 샘플 프로그램



(1) 사전 준비



액키 아트처럼 숫자를 표시하는 텍스트 파일을 준비해 둡니다.

big0.txt
....######......
..##......##....
..##......##....
..##......##....
..##......##....
..##......##....
....######......
................

big1.txt
......##........
..######........
......##........
......##........
......##........
......##........
..##########....
................

big2.txt
....######......
..##......##....
..........##....
......####......
....##..........
..##............
..##########....
................

(이하, 약어)

(2) 동작 확인



실제로 Flyweight 패턴을 활용한 샘플 프로그램을 움직여서 다음과 같은 동작의 모습을 확인하고 싶습니다.
  • 인수의 숫자 순서로 지정된 숫자를 아스키 아트로 표시합니다.
    $ python Main.py 012123
    ....######......
    ..##......##....
    ..##......##....
    ..##......##....
    ..##......##....
    ..##......##....
    ....######......
    ................
    ......##........
    ..######........
    ......##........
    ......##........
    ......##........
    ......##........
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ....##..........
    ..##............
    ..##########....
    ................
    ......##........
    ..######........
    ......##........
    ......##........
    ......##........
    ......##........
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ....##..........
    ..##............
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ..........##....
    ..##......##....
    ....######......
    ................
    

    ■ 샘플 프로그램에 대해 자세히 알아보기



    Git 저장소에도 비슷한 코드가 있습니다.
    htps : // 기주 b. 이 m / 싹 보 / s t dy_ 오 f_로 해 응 _ 파테 r
  • 디렉토리 구성
  • .
    ├── Main.py
    ├── big0.txt
    ├── big1.txt
    ├── big2.txt
    ├── big3.txt
    ├── big4.txt
    ├── big5.txt
    ├── big6.txt
    ├── big7.txt
    ├── big8.txt
    ├── big9.txt
    └── flyweight
        ├── __init__.py
        └── big_char_factory.py
    

    (1) Flyweight(플라이급)의 역



    보통으로 취급하면 프로그램이 무거워지므로 공유하는 것이 좋은 것을 나타내는 역입니다.
    샘플 프로그램에서는, BigChar 클래스가, 이 역할을 노력합니다.

    flyweight/big_char_factory.py
    class BigChar(object):
        def __init__(self, charname):
            try:
                with open("big{0}.txt".format(charname), 'r') as txtfile:
                    data = txtfile.read()
                self.__fontdata = data
            except IOError:
                self.__fontdata = charname + '?'
    
        def __str__(self):
            return self.__fontdata
    

    (2) FlyweightFactory(플라이급의 공장)의 역


    Flyweight 를 만드는 공장의 역할입니다. 이 공장을 사용하여 Flyweight 역할을 만들면 인스턴스가 공유됩니다.
    샘플 프로그램에서는, BigCharFactory 클래스가, 이 역할을 노력합니다.

    flyweight/big_char_factory.py
    class BigCharFactory(object):
        def __init__(self):
            self.__pool = {}
    
        @classmethod
        def getInstance(cls):
            if not hasattr(cls, "_instance"):
                cls._instance = cls()
            return cls._instance
    
        def getBigChar(self, charname):
            bc = self.__pool.get(charname)
            if bc is None:
                bc = BigChar(charname)
                self.__pool[charname] = bc
            return bc
    

    (3) Client(의뢰인)의 역할


    FlyweightFactory 역을 사용해 Flyweight 를 만들어, 그것을 이용하는 역입니다.
    샘플 프로그램에서는, BigString 클래스와 startMain 메소드가, 이 역할을 노력합니다.

    flyweight/big_char_factory.py
    class BigString(object):
        def __init__(self, string):
            self.bigchars = []
            self.factory = BigCharFactory.getInstance()
            for s in string:
                self.bigchars.append(self.factory.getBigChar(s))
    
        def print(self):
            for bc in self.bigchars:
                print(bc)
    

    Main.py
    import sys
    from flyweight.big_char_factory import BigCharFactory, BigString
    
    def startMain(string):
        bs = BigString(string)
        bs.print()
    
    if __name__ == '__main__':
        startMain(sys.argv[1])
    

    ■ 참고 URL


  • 「Java 언어로 배우는 디자인 패턴 입문」을 끝내고(없음)
  • 좋은 웹페이지 즐겨찾기