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) {
// 此为示例代码,在实践中,不应将建造者与使用者放在一个包内,所