创建型模式主要目标是提供一种灵活方式创建对象,同事隐藏创建的具体细节,降低代码耦合度,提高复用性和可维护性。
创建型模式-单例
单例模式,Singleton, 确保只有一实例,并提供全局访问点。
使用场景:配置管理,日志记录, 数据库连接池等。
global.DB,  global.Config 并不是单例模式,而是直接使用全局变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | package database
  import "sync"
  type DB struct { }
  var db *DB
  var once sync.Once
  func initDB(dsn string) *DB { 	return &DB{} }
  func GetDB() *DB { 	once.Do(func() { 		db = initDB("xxx") 	}) 	return db }
   | 
 
单测:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | package database
  import ( 	"fmt" 	"testing" )
  func TestGetDB(t *testing.T) { 	db1 := GetDB() 	db2 := GetDB() 	db3 := GetDB()
  	fmt.Printf("%p\n", db1) 	fmt.Printf("%p\n", db2) 	fmt.Printf("%p\n", db3) }
 
   | 
 
创建型模式-简单工厂模式
目标是将对象的创建和使用分离,解耦合
简单工厂模式:一个工厂类负责创建所有产品,通过条件判断来决定创建哪种产品。
简单工厂并不是正式的设计模式,而是一种编程习惯。(所以有23种设计模式,和24种设计模式两种说法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | package factory_pay
  type Pay interface { 	PayPage(price int64) (string, error) }
  type AliPay struct{}
  func (p *AliPay) PayPage(price int64) (string, error) { 	return "aliPay", nil }
  type WexinPay struct{}
  func (p *WexinPay) PayPage(price int64) (string, error) { 	return "wexinPay", nil }
  type PayType int8
  const ( 	AliPayType   = 1 	WexinPayType = 2 )
  func NewPayPage(payType PayType) Pay { 	switch payType { 	case AliPayType: 		return &AliPay{} 	case WexinPayType: 		return &WexinPay{} 	} 	return nil }
 
   | 
 
单测:
1 2 3 4 5 6 7 8 9 10 11 12 13
   | package factory_pay
  import ( 	"fmt" 	"testing" )
  func TestNewPayPage(t *testing.T) { 	page, _ := NewPayPage(WexinPayType).PayPage(1) 	payPage, _ := NewPayPage(AliPayType).PayPage(1) 	fmt.Println(page) 	fmt.Println(payPage) }
   | 
 
创建型模式-工厂方法模式
工厂方法模式定义了一个创建对象接口,单具体的创建逻辑延迟到了子类种,每一个子类负责创建一种具体的产品
特点:每个产品对应一个工厂类,符合开闭原则,新增产品只需要增加新的工厂类,无需修改现有代码。
使用场景:产品种类较多,且创建逻辑复杂的场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
   | package factory_method
  type Pay interface { 	PayPage(price int64) (string, error) }
  type AliPay struct{}
  func (p *AliPay) PayPage(price int64) (string, error) { 	return "aliPay", nil }
  type WexinPay struct{}
  func (p *WexinPay) PayPage(price int64) (string, error) { 	return "wexinPay", nil }
  type PayType int8
  const ( 	AliPayType   = 1 	WexinPayType = 2 )
  type PayFactory interface { 	CreatePay() Pay }
  type AliPayFactory struct{}
  func (p *AliPayFactory) CreatePay() Pay { 	 	return &AliPay{} }
  type WexinPayFactory struct{}
  func (p *WexinPayFactory) CreatePay() Pay { 	 	return &WexinPay{} }
 
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | package factory_method
  import ( 	"fmt" 	"testing" )
  func TestPayPage(t *testing.T) { 	aliPayFactory := AliPayFactory{} 	aliPay := aliPayFactory.CreatePay() 	fmt.Println(aliPay.PayPage(1))
  	wexinPayFactory := WexinPayFactory{} 	wexinPay := wexinPayFactory.CreatePay() 	fmt.Println(wexinPay.PayPage(1)) }
   | 
 
使用确实麻烦了,但是修改微信支付,不会影响到其他支付。扩展新的支付方式更容易。
创建型模式-抽象工厂模式
每个工厂类可以创建一组相关产品,强调产品族的概念。
使用场景:需要创建一组相关对象的场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
   | package abstract_method
  import "fmt"
  type Pay interface { 	PayPage(price int64) (string, error) }
  type AliPay struct{}
  func (p *AliPay) PayPage(price int64) (string, error) { 	return "aliPay", nil }
  type WexinPay struct{}
  func (p *WexinPay) PayPage(price int64) (string, error) { 	return "wexinPay", nil }
  type PayType int8
  const ( 	AliPayType   = 1 	WexinPayType = 2 )
  type PayFactory interface { 	CreatePay() Pay 	CreateRefund() Refund }
  type AliPayFactory struct{}
  func (p *AliPayFactory) CreatePay() Pay { 	 	return &AliPay{} }
  type WexinPayFactory struct{}
  func (p *WexinPayFactory) CreatePay() Pay { 	 	return &WexinPay{} }
 
  type Refund interface { 	Refund(orderNo string) error }
  type AliRefund struct{}
  func (p *AliRefund) Refund(orderNo string) error { 	fmt.Println("ali 退款") 	return nil }
  type WexinRefund struct{}
  func (p *WexinRefund) Refund(orderNo string) error { 	fmt.Println("wx 退款") 	return nil }
  func (p *AliPayFactory) CreateRefund() Refund { 	return &AliRefund{}
  }
  func (p *WexinPayFactory) CreateRefund() Refund { 	return &WexinRefund{} }
 
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | package abstract_method
  import ( 	"fmt" 	"testing" )
  func TestPayPage(t *testing.T) { 	aliPayFactory := AliPayFactory{} 	aliPay := aliPayFactory.CreatePay() 	fmt.Println(aliPay.PayPage(1)) 	aliPayFactory.CreateRefund().Refund("")
  	wexinPayFactory := WexinPayFactory{} 	wexinPay := wexinPayFactory.CreatePay() 	fmt.Println(wexinPay.PayPage(1)) 	wexinPayFactory.CreateRefund().Refund("") }
 
   | 
 
创建型模式-建造者模式
核心思想: 分步构建复杂对象。 将复杂对象的构建过程分离,分步。 体现单一职责
适用场景:
- 对象的构建过程复杂,包含多个步骤
 
- 对象构建过程需要支持不通的配置
 
比如要建立房子, 需要以下几个元素
房子:最终制品
建造规范:制定包工头需要符合的规范
包工头:按照建造规范建,交付房子
老板:告诉包工头建什么样的房子,获取房子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   | package builder
  import "fmt"
  type House struct { 	Door   string 	Window string }
 
  type HouseBuilder interface { 	buildDoor(val string) 	buildWindow(val string) 	getHouse() *House }
 
  type Bao struct { 	house *House }
  func (b *Bao) getHouse() *House { 	return b.house }
  func (b *Bao) buildDoor(val string) { 	b.house.Door = val 	fmt.Println("门建造成功") }
  func (b *Bao) buildWindow(val string) { 	b.house.Window = val 	fmt.Println("窗户建造成功") }
  func NewBao() *Bao { 	return &Bao{ 		house: &House{}, 	} }
 
  type Boss struct { 	builder HouseBuilder }
  func NewBoss(bao *Bao) *Boss { 	return &Boss{ 		builder: bao, 	} }
  func (b *Boss) GetHouse() *House { 	b.builder.buildDoor("dor") 	b.builder.buildWindow("win") 	return b.builder.getHouse() }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12
   | package builder
  import ( 	"fmt" 	"testing" )
  func TestNewBao(t *testing.T) { 	b := NewBao() 	boss := NewBoss(b) 	fmt.Println(boss.GetHouse()) }
   | 
 
创建型模式-原型模式
通过复制现有对象来创建新对象,而不是通过新建类的方式。
避免重复初始化,特别适用于创建成本较高的对象。
局限:如果遇到应用类型,需要考虑深拷贝浅拷贝
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | package prototype
  type Prototype interface { 	Clone() Prototype }
  type Student struct { 	Name string 	Age  int }
  func (s *Student) Clone() Prototype { 	return &Student{ 		Name: s.Name, 		Age:  s.Age, 	} }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | package prototype
  import ( 	"fmt" 	"testing" )
  func TestStudent_Clone(t *testing.T) { 	s1 := Student{ 		Name: "xxx", 		Age:  18, 	} 	s2 := s1.Clone().(*Student) 	s2.Name = "yyyy" 	s2.Age = 111 	fmt.Println(s1) 	fmt.Println(s2) }
   |