行为模式:负责对象间的高效沟通和职责委派。
创建型模式:提供创建对象的机制, 能够提升已有代码的灵活性和可复用性。
结构型模式:介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。
package hungrytype singleton struct {}// 在类加载时, 就已经初始化了, 如果singleton结
// 构体很大,那么如果用不到就初始化了,非常浪费资源
var instance = &singleton{}
func GetInstance() *singleton {return instance
}
package lazytype singleton struct {}var instance *singleton
// 在需要的时候才初始化, 避免浪费资源
func GetInstance() *singleton {// 加锁是为了解决并发问题m.Lock()defer m.Unlock()if instance == nil {instance = &singleton{}}return instance
}
上面这样加锁是可以解决问题,但是太重了, 程序性能下降很严重。因此出现了下面的double checking lock。
package dclimport "sync"type singleton struct {}var instance *singleton
var m sync.Mutex
func GetInstance() *singleton {// 如果已经不为空就不进入加锁阶段了, 这样就优化了if instance == nil {m.Lock()defer m.Unlock()if instance == nil {// jvm new对象, 分为下面三步(即三个cpu指令)// 1. 给 instance 分配内存// 2. 调用 Singleton 的构造函数来初始化成员变量// 3. 将instance对象指向分配的内存空间(执行完这步 instance 就为非 null 了)// 其中存在cpu指令重排、cpu cache的问题, 因此需要使用volatile修饰instance// 这样就会使用主存, 而不是使用cpu cache, 避免了指令重排的尴尬instance = &singleton{}}}return instance
}
golang内存模型:https://blog.csdn.net/Zerore/article/details/120321985,这一块目前还不太清楚,大致看了下,我觉得golang中也是存在指令重排的,可以使用sync.once原子语言解决指令重排。
package onceimport "sync"type singleton struct{}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {once.Do(func() {instance = &singleton{}})return instance
}
package simpletype Operator interface {GetResult() float64Init(numberA, numberB int)
}// 运算类
type operation struct {NumberA intNumberB int
}func (o *operation) Init(numberA, numberB int) {o.NumberA = numberAo.NumberB = numberB
}type operationAdd struct {operation
}func (a *operationAdd) GetResult() float64 {return float64(a.NumberA + a.NumberB)
}type operationSub struct {operation
}func (s *operationSub) GetResult() float64 {return float64(s.NumberA - s.NumberB)
}// 简单工厂类
type CreateOperationFactory struct {
}// 简单工厂类中只有一个根据参数生产对应产品的方法
func (cof *CreateOperationFactory) CreateOperate(operate string) Operator {var op Operatorswitch operate {case "+":op = &operationAdd{}case "-":op = &operationSub{}}return op
}
客户端代码:
package mainimport ("fmt""factory/simple"
)func main() {cof := new(simple.CreateOperationFactory)op := cof.CreateOperate("-")op.Init(5, 2)fmt.Print(op.GetResult())
}
弊端:违反了开放-封闭原则(对扩展是开放的,而对修改是封闭的),每次增加新产品(比如增加乘除法支持)都需要修改工厂类中的switch语句。
为了符合开放-封闭原则,于是诞生了工厂方法模式。
核心思想:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
。
package methodtype Operator interface {GetResult() float64Init(numberA, numberB int)
}type operation struct {NumberA intNumberB int
}func (o *operation) Init(numberA, numberB int) {o.NumberA = numberAo.NumberB = numberB
}type operationAdd struct {operation
}func (a *operationAdd) GetResult() float64 {return float64(a.NumberA + a.NumberB)
}type operationSub struct {operation
}func (s *operationSub) GetResult() float64 {return float64(s.NumberA - s.NumberB)
}// 相比简单工厂模式, 上面都是一模一样, 只是多了一堆
// 工厂子类, 创建获取产品对象的操作委托给了工厂子类去做
type IFactory interface {CreateOperation() Operator
}type AddFactory struct {}type SubFactory struct {}func (af *AddFactory) CreateOperation() Operator {return &operationAdd{}
}func (sf *SubFactory) CreateOperation() Operator {return &operationSub{}
}
客户端代码:
package mainimport ("fmt""design-mode/method"
)func main() {var operFactory method.IFactory = &method.SubFactory{}oper := operFactory.CreateOperation()oper.Init(5, 2)fmt.Print(oper.GetResult())
}
上一篇:从零开始搭建一个微服务项目(一)