背景:
设计模式是软件设计的基础,那么在不同的开发语言中会有不同的方式进行设计,下面就是采用Go讲解几个基本的设计模式的设计方案:
一. 单例模式
单例是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
// 单例模式
var once sync.Once //一种安全的初始化机制,保证并发的情况下只有一个去执行。
type single struct { // 实体对象结构
}
var singleInstance *single // 声明一个全局的实体对象
func getInstance() *single {
fmt.Println("-----------", singleInstance)
if singleInstance == nil {
once.Do(func() { // 这里采用once.Do是因为只是一个func无法做到并发请求的时候只有一个去创建执行,非并发情况下是没有可以不采用改方法。
fmt.Println("Creating single instance now")
singleInstance = &single{}
})
} else {
fmt.Println("单体的实体已经存在,直接复用")
}
return singleInstance
}
func TestSingle(t *testing.T) {
for i := 0; i < 40; i++ {
go getInstance() // 模拟并发请求去获取单例的实例化对象
}
}
二. 工厂模式
工厂模式分类
1)简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。
2)工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。
3)抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族
工厂方法示例:
type iGun interface { //设计一个通用的接口类型
setName(name string)
setPower(power int)
getName() string
getPower() int
}
type gun struct { // 设计枪对象,然后分别取实现通用接口
name string
power int
}
func (g *gun) setName(name string) {
g.name = name
}
func (g *gun) getName() string {
return g.name
}
func (g *gun) setPower(power int) {
g.power = power
}
func (g *gun) getPower() int {
return g.power
}
type ak47 struct { // 设置指定的产品ak47枪
gun
}
func newAk47() iGun { // 生成ak47的产品
return &ak47{
gun: gun{
name: "AK47 gun",
power: 4,
},
}
}
func getGun(gunType string) (iGun, error) { //获取指定产品的枪,为工厂方法封装体:
if gunType == "ak47" {
return newAk47(), nil
}
return nil, fmt.Errorf("当前动态的添加产品类型!")
}
func TestFactory(t *testing.T) {
ak47, _ := getGun("ak47")
fmt.Println(ak47.getPower())
fmt.Println(ak47.getName())
}
抽象工厂:
类似于上面的工厂模式,只是上面又封装了一层接口interface。抽象工厂定义了用于创建不同产品的接口, 但将实际的创建工作留给了具体工厂类。 每个工厂类型都对应一个特定的产品变体。
三. 适配器模式
适配器是一种结构型设计模式, 它能使不兼容的对象能够相互合作。
适配器可担任两个对象间的封装器, 它会接收对于一个对象的调用, 并将其转换为另一个对象可识别的格式和接口。
// 适配器模式
type computer interface { // 电脑通用接口函数
insertIntoLightningPort()
}
type client struct {
}
func (c *client) insertLightningConnectorIntoComputer(com computer) { // 这里是通用的方法获取相关的电脑
fmt.Println("Client inserts Lightning connector into computer.")
com.insertIntoLightningPort()
}
type mac struct {
}
func (m *mac) insertIntoLightningPort() { //mac电脑实现闪电接口相关的接口函数
fmt.Println("Lightning connector is plugged into mac machine.")
}
type windows struct{}
func (w *windows) insertIntoUSBPort() { //windows电脑实现适配闪电接口转为USB
fmt.Println("USB connector is plugged into windows machine.")
}
// windows电脑适配器
type windowsAdapter struct {
windowMachine *windows
}
func (w *windowsAdapter) insertIntoLightningPort() { // windows电脑实现闪电接口相关的接口函数
fmt.Println("Adapter converts Lightning signal to USB.")
w.windowMachine.insertIntoUSBPort()
}
func TestAdapter(t *testing.T) {
client := client{}
mac := &mac{}
client.insertLightningConnectorIntoComputer(mac) //获取mac的闪电接口
windows := &windows{}
windowsAdapter := &windowsAdapter{
windowMachine: windows,
}
client.insertLightningConnectorIntoComputer(windowsAdapter) //采用适配器进行获取相关的信息
}