Golang에서 디자인 패턴 "Flyweight"를 배우십시오.

17218 단어 5디자인 패턴GoF
GoF의 디자인 패턴을 학습하는 소재로서, 서적 「 증보 개정판 Java 언어로 배우는 디자인 패턴 입문 」가 참고가 되는 것 같네요.
다루어진 예제는 자바 기반이기 때문에 파이썬에서 동등한 사례에 도전한 적이 있었습니다.
Qiita 기사 : "Python에서 디자인 패턴 "Flyweight"배우기"

이번에는 Python으로 구현한 "Flyweight"의 샘플 앱을 Golang에서 다시 구현해 보았습니다.

■ 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 패턴을 활용한 샘플 프로그램을 움직여서 다음과 같은 동작의 모습을 확인하고 싶습니다.
  • 인수의 숫자 순서로 지정된 숫자를 아스키 아트로 표시합니다.
    $ go run Main.go 012123
    ....######......
    ..##......##....
    ..##......##....
    ..##......##....
    ..##......##....
    ..##......##....
    ....######......
    ................
    ......##........
    ..######........
    ......##........
    ......##........
    ......##........
    ......##........
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ....##..........
    ..##............
    ..##########....
    ................
    ......##........
    ..######........
    ......##........
    ......##........
    ......##........
    ......##........
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ....##..........
    ..##............
    ..##########....
    ................
    ....######......
    ..##......##....
    ..........##....
    ......####......
    ..........##....
    ..##......##....
    ....######......
    ................
    

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



    Git 저장소에도 비슷한 코드가 있습니다.
    htps : // 기주 b. 이 m / 싹 / sts dy_o f_ shin gan_pate rn_uh th_go g / t ree /
  • 디렉토리 구성
  • .
    ├── Main.go
    ├── big0.txt
    ├── big1.txt
    ├── big2.txt
    ├── big3.txt
    ├── big4.txt
    ├── big5.txt
    ├── big6.txt
    ├── big7.txt
    ├── big8.txt
    ├── big9.txt
    └── flyweight
        └── big_char_factory.go
    

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



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

    flyweight/big_char_factory.go
    package flyweight
    
    import (
        "fmt"
        "os"
    )
    
    ... (snip)
    
    type bigChar struct {
        fontdata string
    }
    
    func newBigChar(charname string) *bigChar {
        char := &bigChar{}
        data := make([]byte, 256)
        f, err := os.Open(fmt.Sprintf("big%s.txt", charname))
        if err == nil {
            f.Read(data)
            char.fontdata = string(data)
        } else {
            char.fontdata = charname + "?"
        }
        return char
    }
    
    func (b *bigChar) print() {
        fmt.Println(b.fontdata)
    }
    

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


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

    flyweight/big_char_factory.go
    type bigCharFactory struct {
        pool map[string]*bigChar
    }
    
    func newBigCharFactory() *bigCharFactory {
        bigChrFct := &bigCharFactory{
            pool: make(map[string]*bigChar),
        }
        return bigChrFct
    }
    
    var instance *bigCharFactory
    
    func getInstance() *bigCharFactory {
        if instance == nil {
            instance = newBigCharFactory()
        }
        return instance
    }
    
    func (b *bigCharFactory) getBigChar(charname string) *bigChar {
        var bc *bigChar
        if _, ok := b.pool[charname]; !ok {
            bc = newBigChar(charname)
            b.pool[charname] = bc
        } else {
            bc = b.pool[charname]
        }
        return bc
    }
    

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


    FlyweightFactory 역을 사용해 Flyweight 를 만들어, 그것을 이용하는 역입니다.
    샘플 프로그램에서는 BigString 구조체와 startMain 함수가 이 역할을 합니다.

    flyweight/big_char_factory.go
    // BigString is struct
    type BigString struct {
        bigchars []*bigChar
    }
    
    // NewBigString func for initalizing BigString
    func NewBigString(str string) *BigString {
        bigStr := &BigString{}
        factory := getInstance()
        for _, s := range str {
            bigStr.bigchars = append(bigStr.bigchars, factory.getBigChar(string(s)))
        }
        return bigStr
    }
    
    // Print func for print something
    func (b *BigString) Print() {
        for _, bc := range b.bigchars {
            bc.print()
        }
    }
    

    Main.go
    package main
    
    import (
        "flag"
    
        "./flyweight"
    )
    
    func startMain(str string) {
        bs := flyweight.NewBigString(str)
        bs.Print()
    }
    
    func main() {
        flag.Parse()
        startMain(flag.Arg(0))
    }
    

    ■ 참고 URL


  • 파이썬에서 디자인 패턴 'Flyweight' 배우기
  • 좋은 웹페이지 즐겨찾기