# golang design pattern
一個專案可能要有設計模式來規劃,這樣在寫程式的時候才可以不會那麼雜亂
來學習一下設計模式
# unit test
```
├── go.mod
├── main.go
└── untils
├── untils.go
└── untils_test.go
```
```go=
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")
}
}
}
}
```
```go=
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
}
```
```go=
package main
import (
"fmt"
"untilstest/untils"
)
func main() {
a := untils.Students{"qwd"}
fmt.Println(a)
}
```
# decorate pattern
```go=
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
```go=
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
```go=
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
```go=
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
```go=
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
```go=
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()
}