手かきgolang行動型設計モードポリシーモード


手かきgolang行動型設計モードポリシーモード
に縁を付ける
最近設計モードを復習して譚勇徳の<>本シリーズのノートを拝読してgolangを採用して練習するつもりです
ポリシー・モード
    (Strategy Pattern)       (Policy Pattern),
               ,
           ,
                    ,
         。

(       <>)

シーン
  • ある学習者の成績管理システムは、学習者の成績をソートする必要がある
  • 私たちの王二犬は<>の説明に基づいて、バブルソートアルゴリズムを用いて成績ソート機能
  • を実現した.
  • Leaderはコードを審査する時、王二犬の実現は機能を完成したが、sexyが足りないと考え、
  • の改善を要求した.
  • そこで王二犬はアルゴリズム書を引き続き調べ、選択ソートと高速ソートアルゴリズムを加えた.
  • は互換性と拡張性を考慮し、王二犬は戦略モードに基づいて、ソートアルゴリズムを統一インタフェースに抽象化し、Leaderがどれを言ったらいいか、それを使う.

  • デザイン
  • ISortPolicy:ソートアルゴリズムインタフェース
  • tBubbleSortPolicy:バブルソートアルゴリズム、ISortPolicyインタフェース
  • を実現
  • tSelectSortPolicy:ソートアルゴリズムを選択し、ISortPolicyインタフェース
  • を実現する
  • tQuickSortPolicy:高速ソートアルゴリズム、ISortPolicyインタフェースを実現する.内部はついでにLIFOスタック-tIntStackを実現した.

  • ユニットテスト
    policy_pattern_test.go,いくつかのランダム整数を生成し,次いでそれぞれバブル,選択,高速ソートアルゴリズムを用いてソートする
    package behavioral_patterns
    
    import (
        plc "learning/gooop/behavioral_patterns/policy"
        "math/rand"
        "testing"
        "time"
    )
    
    func Test_PolicyPattern(t *testing.T) {
        size := 20
        data := make([]int, size)
        r := rand.New(rand.NewSource(time.Now().Unix()))
        for i, _ := range data {
            data[i] = r.Intn(100)
        }
        t.Logf("UnsortedData \t= %v", data)
    
        fnMakeCopy := func() []int{
            copies := make([]int, size)
            for i,v := range data {
                copies[i] = v
            }
            return copies
        }
    
        fnTestPolicy := func(policy plc.ISortPolicy) {
            sorted := policy.Sort(fnMakeCopy())
            t.Logf("%s \t= %v", policy.Name(), sorted)
        }
    
        fnTestPolicy(plc.NewBubbleSortPolicy())
        fnTestPolicy(plc.NewSelectSortPolicy())
        fnTestPolicy(plc.NewQuickSortPolicy())
    }

    テスト出力
    $ go test -v policy_pattern_test.go 
    === RUN   Test_PolicyPattern
        policy_pattern_test.go:17: UnsortedData     = [19 17 28 36 80 84 70 7 80 68 2 96 94 26 22 31 80 49 49 69]
        policy_pattern_test.go:29: BubbleSort       = [2 7 17 19 22 26 28 31 36 49 49 68 69 70 80 80 80 84 94 96]
        policy_pattern_test.go:29: SelectSort       = [2 7 17 19 22 26 28 31 36 49 49 68 69 70 80 80 80 84 94 96]
        policy_pattern_test.go:29: QuickSort        = [2 7 17 19 22 26 28 31 36 49 49 68 69 70 80 80 80 84 94 96]
    --- PASS: Test_PolicyPattern (0.00s)
    PASS
    ok      command-line-arguments  0.002s

    ISortPolicy.go
    ソートアルゴリズムインタフェース
    package policy
    
    type ISortPolicy interface {
        Name() string
        Sort(data []int) []int
    }

    tBubbleSortPolicy.go
    バブルソートアルゴリズム、ISortPolicyインタフェースを実現
    package policy
    
    //     
    type tBubbleSortPolicy struct {
    }
    
    func NewBubbleSortPolicy() ISortPolicy {
        return &tBubbleSortPolicy{}
    }
    
    func (self *tBubbleSortPolicy) Name() string {
        return "BubbleSort"
    }
    
    func (self *tBubbleSortPolicy) Sort(data []int) []int {
        if data == nil {
            return nil
        }
    
        size := len(data)
        if size <= 1 {
            return data
        }
    
        for {
            i := size - 1
            changed := false
    
            for {
                if i <= 0 {
                    break
                }
                j := i - 1
    
                if data[j] > data[i] {
                    data[i],data[j] = data[j],data[i]
                    changed = true
                }
    
                i--
            }
    
            if !changed {
                break
            }
        }
    
        return data
    }

    tSelectSortPolicy.go
    ソートアルゴリズムを選択し、ISortPolicyインタフェースを実現
    package policy
    
    //     
    type tSelectSortPolicy struct {
    }
    
    func NewSelectSortPolicy() ISortPolicy {
        return &tSelectSortPolicy{}
    }
    
    func (self *tSelectSortPolicy) Name() string {
        return "SelectSort"
    }
    
    func (self *tSelectSortPolicy) Sort(data []int) []int {
        if data == nil {
            return nil
        }
    
        size := len(data)
        if size <= 1 {
            return data
        }
    
        i := 0
        for {
            if i >= size - 1 {
                break
            }
    
            p, m := self.min(data, i + 1, size - 1)
            if m < data[i] {
                data[p], data[i] = data[i], data[p]
            }
    
            i++
        }
    
        return data
    }
    
    func (self *tSelectSortPolicy) min(data []int, from int, to int) (p int, v int) {
        i := from
        p = from
        v = data[from]
    
        if to <= from {
            return p, v
        }
    
        for {
            i++
            if i > to {
                break
            }
    
            if data[i] < v {
                p = i
                v = data[i]
            }
        }
    
        return p, v
    }

    tQuickSortPolicy.go
    高速ソートアルゴリズム、ISortPolicyインタフェースを実現する.内部にはついでにLIFOスタックが実現する.
    package policy
    
    import "errors"
    
    //     
    type tQuickSortPolicy struct {
        mLeftStack *tIntStack
        mRightStack *tIntStack
    }
    
    func NewQuickSortPolicy() ISortPolicy {
        return &tQuickSortPolicy{
            newIntStack(),newIntStack(),
        }
    }
    
    // LIFO 
    type tIntStack struct {
        tail *tIntNode
        size int
    }
    
    type tIntNode struct {
        Value int
        Prev *tIntNode
    }
    
    func newIntNode(value int) *tIntNode {
        return &tIntNode {
            value, nil,
        }
    }
    
    func newIntStack() *tIntStack {
        return &tIntStack{
            nil,
            0,
        }
    }
    
    func (self *tIntStack) Push(i int) {
        node := newIntNode(i)
        node.Prev = self.tail
        self.tail = node
        self.size++
    }
    
    func (self *tIntStack) Pop() (error,int) {
        if self.size > 0 {
            self.size--
            node := self.tail
            self.tail = self.tail.Prev
            return nil, node.Value
    
        } else {
            return errors.New("empty stack"), 0
        }
    }
    
    func (self *tIntStack) Size() int {
        return self.size
    }
    
    func (self *tQuickSortPolicy) Name() string {
        return "QuickSort"
    }
    
    func (self *tQuickSortPolicy) Sort(data []int) []int {
        self.qsort(data, 0, len(data) - 1)
        return data
    }
    
    
    func (self *tQuickSortPolicy) qsort(data []int, from int, to int)  {
        if to <= from {
            return
        }
    
        // only two
        if to == from + 1 {
            if data[to] < data[from] {
                data[from], data[to] = data[to], data[from]
            }
            return
        }
    
        // get pivot
        iPivot := (from + to) / 2
        vPivot := data[iPivot]
    
        // split left and right
        left := 0
        right := 0
        for i := from; i <= to; i++ {
            if i == iPivot {
                continue
            }
    
            v := data[i]
            if v <= vPivot {
                self.mLeftStack.Push(v)
                left++
            } else {
                self.mRightStack.Push(v)
                right++
            }
        }
    
        // pop right stack
        p := to
        for i := right; i > 0; i-- {
            e,v := self.mRightStack.Pop()
            if e != nil {
                panic(e)
            }
            data[p] = v
            p--
        }
    
        // pop pivot
        data[p] = vPivot
        p--
    
        // pop left stack
        for i := left; i > 0; i-- {
            e,v := self.mLeftStack.Pop()
            if e != nil {
                panic(e)
            }
            data[p] = v
            p--
        }
    
        // qsort left and right
        self.qsort(data, from, from + left - 1)
        self.qsort(data, to - right + 1, to)
    }

    ポリシー・モード・ノット
           
    (1)          。
    (2)            , if...else  、switch...case  
    (3)                    。
    
           
    (1)            ,              。
    (2)            ,      。
    
    (       <>)

    (end)