golang design pattern

一個專案可能要有設計模式來規劃,這樣在寫程式的時候才可以不會那麼雜亂 來學習一下設計模式

unit test

code
├── go.mod
├── main.go
└── untils
    ├── untils.go
    └── untils_test.go
code
package untils

import (
    "fmt"
    "testing"
)

type test struct {
    Name  string
    Score int
}

func TestTeststruct(t *testing.T) {
    a := Students{"qwd", 50}
    b := Students{"qwd", 90}

    c :=
        []test{
            {
                "qwd",
                50,
            },
            {
                "qwd",
                60,
            },
        }

    for _, info := range c {

        if a.check(info.Name) == 0 {
            fmt.Println(a, info.Name, "a check no ok")
            t.Error("wrong result")
        } else if b.check(info.Name) == 0 {
            fmt.Println(b, info.Name, "b check no ok")
            t.Error("wrong result")
        } else {
            fmt.Println(a, info.Name, "both check ok")

            if a.checksco(info.Score) == 2 {
                fmt.Println(a, info.Name, "a no pass")
            } else {
                fmt.Println(a, info.Name, "a pass")
            }
            if b.checksco(info.Score) == 2 {
                fmt.Println(a, info.Name, "b no pass")
            } else {
                fmt.Println(b, info.Name, "b pass")
            }
        }
    }

}
code
package untils

type Students struct {
    Name  string
    Score int
}

func (g *Students) check(checkname string) int {
    if checkname == g.Name {

        return 1
    } else {

        return 0
    }

}

func (g *Students) checksco(avg int) int {
    if g.Score < avg {
        return 2
    } else if g.Score >= avg {
        return 3
    } else if g.Score >= 90 {
        return 4
    }

    return -1
}
code
package main

import (
    "fmt"
    "untilstest/untils"
)

func main() {
    a := untils.Students{"qwd"}
    fmt.Println(a)
}

decorate pattern

code
package main

import "fmt"

type Testbox struct {
    price int
}
type ITest interface {
    Add(price int) int
}
type Type1 struct {
    ITest
}

type Type2 struct {
    ITest
}

func (ty1 *Type1) Add(price int) int {
    return price * 10

}
func (ty2 *Type2) Add(price int) int {
    return price * 20

}

func (tb *Testbox) GetTotal() int {
    return tb.price

}
func (tb *Testbox) AddTotal(i ITest, price int) {
    tb.price = tb.price + i.Add(price)
}
func main() {
    a := Testbox{}
    a.AddTotal(&Type1{}, 1)
    a.AddTotal(&Type2{}, 4)
    fmt.Println(a.GetTotal())

}

command pattern

code
package main

import "fmt"

type TVConsole struct {
    Pwr Power
}

type Power struct {
    ICommand
    IsOn bool
}

func (p *Power) Exec() {
    p.PressPower()
}

func (p *Power) PressPower() {
    p.IsOn = !p.IsOn
    fmt.Println("POWER NOW IS ", p.IsOn)
}

type Controller struct {
    Buttons []ICommand
}

type ICommand interface {
    Exec()
}

type DefCommand struct {
    ICommand
}

func (df *DefCommand) Exec() {
    fmt.Println("Do nothing!! ")

}

func (c *Controller) ResetButtons() {
    c.Buttons = []ICommand{}
    i := 0
    for i < 10 {
        c.Buttons = append(c.Buttons, &DefCommand{})
        i++
    }

}
func (c *Controller) SetupButton(iBtn int, iCmd ICommand) {
    c.Buttons[iBtn] = iCmd

}
func main() {
    tv := TVConsole{}
    tv.Pwr.PressPower()
    tv.Pwr.PressPower()
    c := Controller{}
    c.ResetButtons()
    fmt.Println(len(c.Buttons))
    c.Buttons[0].Exec()
    c.SetupButton(0, &tv.Pwr)
    c.Buttons[0].Exec()
}

observe

code
package main

import "fmt"

type Bus struct {
    Obs []IObserve
}

func (b *Bus) Register(o IObserve) {
    b.Obs = append(b.Obs, o)

}
func (b *Bus) Remove(o IObserve) {
    for i := range b.Obs {
        if b.Obs[i] == o {
            b.Obs = append(b.Obs[:i], b.Obs[:i+1]...)
            return
        }

    }

}
func (b *Bus) Notify(s string) {
    for _, o := range b.Obs {
        o.Update(s)
    }

}

type IObserve interface {
    Update(s string)
}
type Station struct {
}

func (st *Station) Update(s string) {
    fmt.Println("Station Update", s)
}

type Passanger struct {
}

func (pa *Passanger) Update(s string) {
    fmt.Println("Passanger Update", s)
}

func main() {
    bus := Bus{}
    // p := &Passanger{}
    s1 := &Station{}
    s2 := &Station{}
    // bus.Register(p)
    bus.Register(s1)
    bus.Register(s2)
    bus.Notify("s01")

    bus.Notify("s02")
}

strategy

code
package main

import "fmt"

type Sensor struct {
}

func (s *Sensor) TouchIDCard() {
    fmt.Println("touchid")
}

type ComA struct {
    CheckInclock Sensor
}

func (ca *ComA) CheckIn() {
    fmt.Println("Coma CheckIn")
    ca.CheckInclock.TouchIDCard()

}

type PaperCard struct {
}

func (pc *PaperCard) InsertSalayCard() {
    fmt.Println("insert")

}

type ComB struct {
    CheckEq PaperCard
}

func (cb *ComB) CheckIn() {
    fmt.Println("Coma CheckIn")
    cb.CheckEq.InsertSalayCard()

}

func main() {
    a := ComA{
        CheckInclock: Sensor{},
    }

    b := ComB{
        CheckEq: PaperCard{},
    }
    a.CheckIn()
    b.CheckIn()
}

adapter

code
package main

import (
    "log"
    "strings"
)

type IForex interface {
    CcyPair() string
}
type Forex struct {
    BaseCcy string
    TerCcy  string
}

func (fx *Forex) CcyPair() string {
    return fx.BaseCcy + fx.TerCcy

}

type IStock interface {
    Ticker() string
}

func (s *Stock) Ticker() string {
    return strings.Split(s.TickerName, "-")[0]

}

type Stock struct {
    TickerName string
    IStock
}

type FXAdapter struct {
    IForex
    IStock
}

func (fxa *FXAdapter) Ticker() string {
    return fxa.IForex.CcyPair()
}
func (fxa *FXAdapter) Ticker2() string {
    return fxa.IStock.Ticker()
}

// func (fxa *FXAdapter) Ticker() {
//  fxa.IForex.CcyPair()
// }
func main() {
    f := Forex{
        BaseCcy: "usd",
        TerCcy:  "twd",
    }

    st := Stock{
        TickerName: "2330-TSMC",
    }

    sta := FXAdapter{
        IForex: &f,
        IStock: &st,
    }
    // log.Println(f.CcyPair())
    // log.Println(st.Ticker())
    log.Println(sta.Ticker())
    log.Println(sta.Ticker2())
}

facotry

code
package main

import "fmt"

type LaunchBox struct {
    Meal     string
    Tool     string
    stayOrGo string
    Drink    string
}

func (lb *LaunchBox) Order(stayOrGo string, meal string) {
    fmt.Println("接受訂單")
    lb.Meal = meal
    lb.stayOrGo = stayOrGo

}
func (lb *LaunchBox) Prepare() {
    fmt.Println("準備")
    switch lb.stayOrGo {
    case "內用":
        lb.Tool = "餐盤"
        lb.Drink = "湯"
    case "外帶":
        lb.Tool = "塑膠袋"
        lb.Drink = "飲料"
    }

}
func (lb *LaunchBox) Deliver() {
    fmt.Println("訂單", lb.Drink, lb.Meal, lb.Tool)

}
func main() {
    box := LaunchBox{}
    box.Order("外帶", "雞腿飯")
    box.Prepare()
    box.Deliver()
    box.Order("內用", "雞腿飯")
    box.Prepare()
    box.Deliver()

}