手かきgolang行動型設計モードポリシーモード
7406 ワード
手かきgolang行動型設計モードポリシーモード
に縁を付ける
最近設計モードを復習して譚勇徳の<>本シリーズのノートを拝読してgolangを採用して練習するつもりです
ポリシー・モード
シーンある学習者の成績管理システムは、学習者の成績をソートする必要がある 私たちの王二犬は<>の説明に基づいて、バブルソートアルゴリズムを用いて成績ソート機能 を実現した. Leaderはコードを審査する時、王二犬の実現は機能を完成したが、sexyが足りないと考え、 の改善を要求した.そこで王二犬はアルゴリズム書を引き続き調べ、選択ソートと高速ソートアルゴリズムを加えた. は互換性と拡張性を考慮し、王二犬は戦略モードに基づいて、ソートアルゴリズムを統一インタフェースに抽象化し、Leaderがどれを言ったらいいか、それを使う.
デザイン ISortPolicy:ソートアルゴリズムインタフェース tBubbleSortPolicy:バブルソートアルゴリズム、ISortPolicyインタフェース を実現 tSelectSortPolicy:ソートアルゴリズムを選択し、ISortPolicyインタフェース を実現する tQuickSortPolicy:高速ソートアルゴリズム、ISortPolicyインタフェースを実現する.内部はついでにLIFOスタック-tIntStackを実現した.
ユニットテスト
policy_pattern_test.go,いくつかのランダム整数を生成し,次いでそれぞれバブル,選択,高速ソートアルゴリズムを用いてソートする
テスト出力
ISortPolicy.go
ソートアルゴリズムインタフェース
tBubbleSortPolicy.go
バブルソートアルゴリズム、ISortPolicyインタフェースを実現
tSelectSortPolicy.go
ソートアルゴリズムを選択し、ISortPolicyインタフェースを実現
tQuickSortPolicy.go
高速ソートアルゴリズム、ISortPolicyインタフェースを実現する.内部にはついでにLIFOスタックが実現する.
ポリシー・モード・ノット
(end)
に縁を付ける
最近設計モードを復習して譚勇徳の<>本シリーズのノートを拝読してgolangを採用して練習するつもりです
ポリシー・モード
(Strategy Pattern) (Policy Pattern),
,
,
,
。
( <>)
シーン
デザイン
ユニットテスト
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)