go中常用的设计模式。
简单工厂
1package main
2
3import "fmt"
4
5//中国人,你好
6//英国人 ,hello
7type API interface{//接口
8 Say(name string)string
9}
10
11func NewAPI(str string)API{
12 if str=="en"{
13 return &English{}
14 }else if str=="cn"{
15 return &Chinese{}
16 } else{
17 return nil
18 }
19}
20
21
22type Chinese struct{}
23func (*Chinese) Say(name string)string{
24 return "你好"+name
25}
26
27type English struct{}
28func (*English) Say(name string)string{
29 return "hello"+name
30}
31
32type Japanese struct{}
33func (*Japanese) Say(name string)string{
34 return "鬼子你好"+name
35}
36
37func main11(){
38 api:=NewAPI("cn")
39 server:=api.Say("张海涛")
40 fmt.Println(server)
41}
42func main12(){
43 api:=NewAPI("en")
44 server:=api.Say("Alex")
45 fmt.Println(server)
46}
函数选项模式
这个是go语言比较特殊的。有些开源项目如grpc的链接也是用了这个模式.
1package main
2
3import "fmt"
4
5type DbConfig struct {
6 host string
7 port int
8 password string
9 username string
10 printLog bool
11}
12
13type Option func(config *DbConfig)
14
15func WithPrintLog() Option {
16 return func(config *DbConfig) {
17 config.printLog = true
18 }
19}
20
21func NewDbConfig(Options ...Option) *DbConfig {
22 //默认值
23 var config = &DbConfig{
24 host: "127.0.0.1",
25 port: 3306,
26 }
27 for _, option := range Options {
28 option(config)
29 }
30 return config
31}
32
33func main() {
34 dbConfig := NewDbConfig(WithPrintLog())
35 fmt.Printf("%+v", dbConfig)
36}
单例模式
官方提供了sync.Once ,直接加锁实现也可以,就是性能不高。
1package main
2
3import (
4 "fmt"
5 "sync"
6 "time"
7)
8
9type DbConfig struct {
10 host string
11 port int
12 password string
13 username string
14 printLog bool
15}
16
17type Option func(config *DbConfig)
18
19func WithPrintLog() Option {
20 return func(config *DbConfig) {
21 config.printLog = true
22 }
23}
24
25func NewDbConfig(Options ...Option) *DbConfig {
26 //默认值
27 var config = &DbConfig{
28 host: "127.0.0.1",
29 port: 3306,
30 }
31 for _, option := range Options {
32 option(config)
33 }
34 return config
35}
36
37var once sync.Once
38var dbConfig *DbConfig
39
40func GetDbConfig() *DbConfig {
41 once.Do(func() {
42 dbConfig = NewDbConfig(WithPrintLog())
43 fmt.Printf("%+v\n", dbConfig)
44 })
45 return dbConfig
46}
47
48func main() {
49 go func() {
50 fmt.Printf("%p\n", GetDbConfig())
51 }()
52 go func() {
53 fmt.Printf("%p\n", GetDbConfig())
54 }()
55 go func() {
56 fmt.Printf("%p\n", GetDbConfig())
57 }()
58 time.Sleep(time.Second)
59}
责任链模式
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者 。
如gin 的中间件实现。
1type Context struct {
2 // ...
3
4 // handlers 是一个包含执行函数的数组
5 // type HandlersChain []HandlerFunc
6 handlers HandlersChain
7 // index 表示当前执行到哪个位置了
8 index int8
9
10 // ...
11}
12
13// Next 会按照顺序将一个个中间件执行完毕
14// 并且 Next 也可以在中间件中进行调用,达到请求前以及请求后的处理
15// Next should be used only inside middleware.
16// It executes the pending handlers in the chain inside the calling handler.
17// See example in GitHub.
18func (c *Context) Next() {
19 c.index++
20 for c.index < int8(len(c.handlers)) {
21 c.handlers[c.index](c)
22 c.index++
23 }
24}
原型模式
主要用于快速复制复杂的对象 。 结合注册树。
1package main
2
3import "fmt"
4
5//原型对象需要实现的接口
6//map map[""1232]=1232
7//拷贝原有的对象
8
9
10type Cloneable interface{
11 Clone() Cloneable
12}
13
14//原型对象的类
15type PrototypeManger struct{
16 prototypes map[string]Cloneable
17}
18//构造初始化
19func NewPrototypeManger() * PrototypeManger{
20 return &PrototypeManger{make(map[string]Cloneable)}
21}
22//抓取
23func (p* PrototypeManger)Get(name string)Cloneable{
24 return p.prototypes[name]
25}
26//设置
27func (p* PrototypeManger)Set(name string, prototype Cloneable){
28 p.prototypes[name]=prototype
29}
30
31
32type Type1 struct{
33 name string
34}
35func (t*Type1)Clone() Cloneable{
36 //tc:=*t
37 //return &tc 深复制
38 return t
39}
40
41type Type2 struct{
42 name string
43}
44func (t*Type2)Clone() Cloneable{
45 tc:=*t //开辟内存新建变量,存储指针指向的内容
46 return &tc //返回地址
47}
48
49
50
51func main(){
52 mgr:=NewPrototypeManger()
53 t1:=&Type1{name:"type1"}
54 mgr.Set("t1",t1)
55 t11:=mgr.Get("t1")
56 t22:=t11.Clone()//复制
57 if t11==t22{
58 fmt.Println("浅复制")
59 }else{
60 fmt.Println("深复制")
61 }
62}
装饰器模式
装饰器模式是指不在改变现有对象结构的情况下,动态地给改对象增加一些功能的设计模式
实例增加 装饰的组建(如手机基础组件) . 在实例进行执行功能的时候,自动加装饰的部分代码进行执行
1package decorator
2
3type Phone interface {
4 GetPrice() float32
5}
6
7//装饰
8type Decorator struct {
9 Phone Phone
10}
11
12//装饰设置组件方法
13func (d *Decorator) SetComponent(c Phone) {
14 d.Phone = c
15}
16
17//装饰方法
18func (d *Decorator) GetPrice() {
19 if d.Phone != nil {
20 d.Phone.GetPrice()
21 }
22}
23
24//基础零件
25type BaseParts struct {
26}
27
28//获取基础零件手机价格
29func (p *BaseParts) GetPrice() float32 {
30 return 2000
31}
32
33type IPhone struct {
34 Decorator
35}
36
37//获取IPhone价格
38func (c *IPhone) GetPrice() float32 {
39 phonePrice := c.Phone.GetPrice()
40 return phonePrice + 6000
41}
42
43type Xiaomi struct {
44 Decorator
45}
46
47//小米手机的价格
48func (c *Xiaomi) GetPrice() float32 {
49 phonePrice := c.Phone.GetPrice()
50 return phonePrice + 1000
51}
1package decorator
2
3import (
4 "fmt"
5 "testing"
6)
7
8func TestDecorator(t *testing.T) {
9 //具体零件
10 phone := &BaseParts{}
11 fmt.Printf("基础零件的价格为:%f\n", phone.GetPrice())
12
13 //定义添加IPhone手机
14 iPhone := &IPhone{}
15 iPhone.SetComponent(phone)
16 fmt.Printf("苹果的价格为:%f\n", iPhone.GetPrice())
17
18 //定义添加Xiaomi手机
19 xiaomi := &Xiaomi{}
20 xiaomi.SetComponent(phone)
21 fmt.Printf("小米的价格为:%f\n", xiaomi.GetPrice())
22
23}