Go语言编写设计模式

1. 抽象工厂模式

abstract_factory.go


// package abstract_factory 抽象工厂模式
package abstract_factory

import "fmt"

// FruitFactory 水果工厂接口
type FruitFactory interface {
 // CreateFruit 生产水果
 CreateFruit() Fruit
}

//AppleFactory 苹果工厂,实现FruitFactory接口
type AppleFactory struct{}

//BananaFactory 香蕉工厂,实现FruitFactory接口
type BananaFactory struct{}

//OrangeFactory 橘子工厂,实现FruitFactory接口
type OrangeFactory struct{}

// CreateFruit 苹果工厂生产苹果
func (appleFactory AppleFactory) CreateFruit() Fruit {
 return &Apple{}
}

// CreateFruit 香蕉工厂生产香蕉
func (bananaFactory BananaFactory) CreateFruit() Fruit {
 return &Banana{}
}

// CreateFruit 橘子工厂生产橘子
func (orangeFactory OrangeFactory) CreateFruit() Fruit {
 return &Orange{}
}

// Fruit 水果接口
type Fruit interface {
 // Eat 吃水果
 Eat()
}

// Apple 苹果,实现Fruit接口
type Apple struct{}

// Banana 香蕉,实现Fruit接口
type Banana struct{}

// Orange 橘子,实现Fruit接口
type Orange struct{}

// Eat 吃苹果
func (apple Apple) Eat() {
 fmt.Println("吃苹果")
}

// Eat 吃香蕉
func (banana Banana) Eat() {
 fmt.Println("吃香蕉")
}

// Eat 吃橘子
func (orange Orange) Eat() {
 fmt.Println("吃橘子")
}


abstract_factory_test.go

package abstract_factory

import "testing"

func Test(t *testing.T) {
 t.Run("abstract_factory: ", ProduceFruitAndEat)
}

func ProduceFruitAndEat(t *testing.T) {
 var factory FruitFactory
 var apple, banana, orange Fruit

 //创建苹果工厂,生产苹果,吃苹果
 factory = &AppleFactory{}
 apple = factory.CreateFruit()
 apple.Eat()

 //创建香蕉工厂,生产香蕉,吃香蕉
 factory = &BananaFactory{}
 banana = factory.CreateFruit()
 banana.Eat()

 //创建橘子工厂,生产橘子,吃橘子
 factory = &OrangeFactory{}
 orange = factory.CreateFruit()
 orange.Eat()
}

2. 适配器模式

adapter.go

// package adapter 适配器,以手机充电为例,适配器将220v电压转为5v电压
package adapter

import "fmt"

// Volts220 源结构体,电压220v
type Volts220 struct{}

// OutputPower 输出电压,实现了Adaptee接口
func (v Volts220) OutputPower() {
 fmt.Println("电源输出了220V电压")
}

// Adaptee 源接口
type Adaptee interface {
 // OutputPower 输出电压
 OutputPower()
}

// Target 目的接口
type Target interface {
 // CovertTo5V 转换到5V电压
 CovertTo5V()
}

// Adapter 适配器结构体,嵌套Adaptee接口,实现Target接口
type Adapter struct {
 Adaptee
}

// CovertTo5V 转换到5V电压
func (a Adapter) CovertTo5V() {
 //这里实现自己的转换逻辑,会调用源结构体的方法
 a.OutputPower()
 fmt.Println("通过手机电源适配器,转成了5V电压,可供手机充电")
}

adapter_test.go

package adapter

import "testing"

func Test(t *testing.T) {
 t.Run("adaptor: ", ConvertVolts)
}

func ConvertVolts(t *testing.T) {
 var adaptee Adaptee
 adaptee = &Volts220{}

 var target Target
 target = &Adapter{adaptee}
 target.CovertTo5V()
}

3. 桥接模式

bridge.go

// package bridge 桥接模式,以订购咖啡为例,两个纬度,分别为大中小杯,加糖加奶
package bridge

import "fmt"

// ICoffee 咖啡接口
type ICoffee interface {
 // OrderCoffee 订购咖啡
 OrderCoffee()
}

// LargeCoffee 大杯咖啡,实现ICoffee接口
type LargeCoffee struct {
 ICoffeeAddtion
}

// MediumCoffee 中杯咖啡,实现ICoffee接口
type MediumCoffee struct {
 ICoffeeAddtion
}

// SmallCoffee 小杯咖啡,实现ICoffee接口
type SmallCoffee struct {
 ICoffeeAddtion
}

// OrderCoffee 订购大杯咖啡
func (lc LargeCoffee) OrderCoffee() {
 fmt.Println("订购了大杯咖啡")
 lc.AddSomething()
}

// OrderCoffee 订购中杯咖啡
func (mc MediumCoffee) OrderCoffee() {
 fmt.Println("订购了中杯咖啡")
 mc.AddSomething()
}

// OrderCoffee 订购小杯咖啡
func (sc SmallCoffee) OrderCoffee() {
 fmt.Println("订购了小杯咖啡")
 sc.AddSomething()
}

// CoffeeCupType 咖啡容量类型
type CoffeeCupType uint8

const (
 // CoffeeCupTypeLarge 大杯咖啡
 CoffeeCupTypeLarge = iota
 // CoffeeCupTypeMedium 中杯咖啡
 CoffeeCupTypeMedium = iota
 // CoffeeCupTypeSmall 小杯咖啡
 CoffeeCupTypeSmall = iota
)

// CoffeeFuncMap 全局可导出变量,咖啡类型与创建咖啡对象的map,用于减小圈复杂度
var CoffeeFuncMap = map[CoffeeCupType]func(coffeeAddtion ICoffeeAddtion) ICoffee{
 CoffeeCupTypeLarge:  NewLargeCoffee,
 CoffeeCupTypeMedium: NewMediumCoffee,
 CoffeeCupTypeSmall:  NewSmallCoffee,
}

// NewCoffee 创建咖啡接口对象的简单工厂,根据咖啡容量类型,获取创建接口对象的func
func NewCoffee(cupType CoffeeCupType, coffeeAddtion ICoffeeAddtion) ICoffee {
 if handler, ok := CoffeeFuncMap[cupType]; ok {
  return handler(coffeeAddtion)
 }
 return nil
}

// NewLargeCoffee 创建大杯咖啡对象
func NewLargeCoffee(coffeeAddtion ICoffeeAddtion) ICoffee {
 return &LargeCoffee{coffeeAddtion}
}

// NewMediumCoffee 创建中杯咖啡对象
func NewMediumCoffee(coffeeAddtion ICoffeeAddtion) ICoffee {
 return &MediumCoffee{coffeeAddtion}
}

// NewSmallCoffee 创建小杯咖啡对象
func NewSmallCoffee(coffeeAddtion ICoffeeAddtion) ICoffee {
 return &SmallCoffee{coffeeAddtion}
}

// ICoffeeAddtion 咖啡额外添加接口
type ICoffeeAddtion interface {
 //AddSomething 添加某种食物
 AddSomething()
}

// Milk 加奶,实现ICoffeeAddtion接口
type Milk struct{}

// Sugar 加糖,实现ICoffeeAddtion接口
type Sugar struct{}

// AddSomething Milk实现加奶
func (milk Milk) AddSomething() {
 fmt.Println("加奶")
}

//AddSomething Sugar实现加糖
func (sugar Sugar) AddSomething() {
 fmt.Println("加糖")
}

// CoffeeAddtionType 咖啡额外添加类型
type CoffeeAddtionType uint8

const (
 // CoffeeAddtionTypeMilk 咖啡额外添加牛奶
 CoffeeAddtionTypeMilk = iota
 // CoffeeAddtionTypeSugar 咖啡额外添加糖
 CoffeeAddtionTypeSugar = iota
)

// CoffeeAddtionFuncMap 全局可导出变量,咖啡额外添加类型与创建咖啡额外添加对象的map,用于减小圈复杂度
var CoffeeAddtionFuncMap = map[CoffeeAddtionType]func() ICoffeeAddtion{
 CoffeeAddtionTypeMilk:  NewCoffeeAddtionMilk,
 CoffeeAddtionTypeSugar: NewCoffeeAddtionSugar,
}

// NewCoffeeAddtion 创建咖啡额外添加接口对象的简单工厂,根据咖啡额外添加类型,获取创建接口对象的func
func NewCoffeeAddtion(addtionType CoffeeAddtionType) ICoffeeAddtion {
 if handler, ok := CoffeeAddtionFuncMap[addtionType]; ok {
  return handler()
 }
 return nil
}

// NewCoffeeAddtionMilk 创建咖啡额外加奶
func NewCoffeeAddtionMilk() ICoffeeAddtion {
 return &Milk{}
}

// NewCoffeeAddtionMilk 创建咖啡额外加糖
func NewCoffeeAddtionSugar() ICoffeeAddtion {
 return &Sugar{}
}


bridge_test.go


package bridge

import "testing"

func Test(t *testing.T) {
 t.Run("large-milk: ", OrderLargeMilkCoffee)
 t.Run("large-sugar: ", OrderLargeSugarCoffee)
 t.Run("medium-milk: ", OrderMediumMilkCoffee)
 t.Run("smarll-sugar: ", OrderSmallSugarCoffee)
}

func OrderLargeMilkCoffee(t *testing.T) {
 var coffeeAddtion ICoffeeAddtion
 coffeeAddtion = NewCoffeeAddtion(CoffeeAddtionTypeMilk)
 var coffee ICoffee
 coffee = NewCoffee(CoffeeCupTypeLarge, coffeeAddtion)
 coffee.OrderCoffee()
}

func OrderLargeSugarCoffee(t *testing.T) {
 var coffeeAddtion ICoffeeAddtion
 coffeeAddtion = NewCoffeeAddtion(CoffeeAddtionTypeSugar)
 var coffee ICoffee
 coffee = NewCoffee(CoffeeCupTypeLarge, coffeeAddtion)
 coffee.OrderCoffee()
}

func OrderMediumMilkCoffee(t *testing.T) {
 var coffeeAddtion ICoffeeAddtion
 coffeeAddtion = NewCoffeeAddtion(CoffeeAddtionTypeMilk)
 var coffee ICoffee
 coffee = NewCoffee(CoffeeCupTypeMedium, coffeeAddtion)
 coffee.OrderCoffee()
}

func OrderSmallSugarCoffee(t *testing.T) {
 var coffeeAddtion ICoffeeAddtion
 coffeeAddtion = NewCoffeeAddtion(CoffeeAddtionTypeSugar)
 var coffee ICoffee
 coffee = NewCoffee(CoffeeCupTypeSmall, coffeeAddtion)
 coffee.OrderCoffee()
}

资料领取直通车:Golang云原生最新资料+视频学习路线

Go语言学习地址:Golang DevOps项目实战

4. 建造者模式

builder.go

//package builder 建造者模式
package builder

const (
 // Success 成功
 Success = 0
 // ErrCodeNameRequired 名字必填
 ErrCodeNameRequired = -10001
 // ErrCodeMinIdleMoreThanMaxIdle 最小空闲数超过了最大空闲数
 ErrCodeMinIdleMoreThanMaxIdle = -10002
 // ErrCodeMaxTotalLessThanOrEqualToZero 最大连接数必须大于0
 ErrCodeMaxTotalMustMoreThanZero = -10003
 // ErrCodeMaxIdleMustMoreThanZero 最大空闲数必须大于0
 ErrCodeMaxIdleMustMoreThanZero = -10004
 // ErrCodeMinIdleMustMoreThanZero 最小空闲数必须大于0
 ErrCodeMinIdleMustMoreThanZero = -10005
 // ErrCodeMaxTotalNotSet 最大连接数未设置
 ErrCodeMaxTotalNotSet = -10006
 // ErrCodeMaxIdleNotSet 最大空闲连接数未设置
 ErrCodeMaxIdleNotSet = -10007
 // ErrCodeMinIdleNotSet 最小空闲连接数未设置
 ErrCodeMinIdleNotSet = -10008
)

// errMap 错误信息与错误码的配置
var errMap = map[int16]string{
 Success:                         "ok",
 ErrCodeNameRequired:             "名字必填",
 ErrCodeMinIdleMoreThanMaxIdle:   "最小空闲数超过了最大空闲数",
 ErrCodeMaxTotalMustMoreThanZero: "最大连接数必须大于0",
 ErrCodeMaxIdleMustMoreThanZero:  "最大空闲连接数必须大于0",
 ErrCodeMinIdleMustMoreThanZero:  "最小空闲连接数必须大于0",
 ErrCodeMaxTotalNotSet:           "最大连接数未设置",
 ErrCodeMaxIdleNotSet:            "最大空闲连接数未设置",
 ErrCodeMinIdleNotSet:            "最小空闲连接数未设置",
}

// resourcePoolConfig 资源池配置,不可导出
type resourcePoolConfig struct {
 // name 名字,不可导出,必填
 name string
 // maxTotal 最大连接数,不可导出,必填
 maxTotal uint16
 // maxIdle 最大空闲连接数,不可导出,必填
 maxIdle uint16
 // minIdle 最小空闲连接数,不可导出,不必填,但填写必须大于0
 minIdle uint16
}

// Builder 建造者接口
type Builder interface {
 // Build 创建对象
 Build() int16
}

// ResourcePoolBuild 资源池建造者,实现Builder接口
type ResourcePoolBuild struct {
 // resourcePoolConfig 嵌套资源池配置
 resourcePoolConfig
}

// Build 创建对象
func (build *ResourcePoolBuild) Build() int16 {
 // 这一串的判断可以保证builder里要求必须设置的属性,都能够设置
 if len(build.name) == 0 {
  return ErrCodeNameRequired
 }
 if build.maxTotal == 0 {
  return ErrCodeMaxTotalNotSet
 }
 if build.maxIdle == 0 {
  return ErrCodeMaxIdleNotSet
 }

 // 对设置后的对象,做整体的逻辑性验证
 if build.minIdle > build.maxIdle {
  return ErrCodeMinIdleMoreThanMaxIdle
 }
 return Success
}

// SetName 设置名字,并进行校验
func (build *ResourcePoolBuild) SetName(name string) int16 {
 if len(name) == 0 {
  return ErrCodeNameRequired
 }
 build.name = name
 return Success
}

// SetMaxTotal 设置最大连接数,并进行校验
func (build *ResourcePoolBuild) SetMaxTotal(maxTotal uint16) int16 {
 if maxTotal <= 0 {
  return ErrCodeMaxTotalMustMoreThanZero
 }
 build.maxTotal = maxTotal
 return Success
}

// SetMaxIdle 设置最大空闲连接数,并信息校验
func (build *ResourcePoolBuild) SetMaxIdle(maxIdle uint16) int16 {
 if maxIdle <= 0 {
  return ErrCodeMaxIdleMustMoreThanZero
 }
 build.maxIdle = maxIdle
 return Success
}

// SetMinIdle 设置最小空闲连接数,并进行校验
func (build *ResourcePoolBuild) SetMinIdle(minIdle uint16) int16 {
 if minIdle <= 0 {
  return ErrCodeMinIdleMustMoreThanZero
 }
 build.minIdle = minIdle
 return Success
}


builder_test.go

package builder

import (
 "fmt"
 "testing"
)

func Test(t *testing.T) {
 t.Run("builder-maxTotalNotSet: ", maxTotalNotSet)
 t.Run("builder-minIdleMoreThanMaxIdle: ", minIdleMoreThanMaxIdle)
 t.Run("builder-buildSuccess: ", buildSuccess)
}

func maxTotalNotSet(t *testing.T) {
 // 此为示例代码,在实践中,不应将建造者与使用者放在一个包内,所以这里假设不能直接访问resourcePoolConfig
 build := &ResourcePoolBuild{}
 build.SetName("mysql连接池")
 build.SetMaxIdle(10)
 errCode := build.Build()
 fmt.Println(fmt.Sprintf("建造资源池配置:%s", errMap[errCode]))
}

func minIdleMoreThanMaxIdle(t *testing.T) {
 // 此为示例代码,在实践中,不应将建造者与使用者放在一个包内,所
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值