工厂模式是创建型设计模式,在工厂模式中,父类决定实例的生成方式,但并不决定所生成的具体的类,具体的处理全部交给子类负责。
工厂模式是使用Template模版模式来构建生成实例的工厂。这也是为什么我们要先学习模版模式的原因,而不像其他博主按照设计模式的类型划分后一类一类的学习。
场景
本期我们以一个制作身份证(IDCard)的程序来演示工厂模式。
基础类型和接口
老规矩,先定义基础类型和抽象接口。
首先我们先定义一个工厂接口Factory,并定义了3个方法,分别是对外公开生成实例的Create(),以及被封装的实际生成实例的createProduct()和保存以生成实例的registerProduct()
// 工厂接口
type Factory interface {
// 对外公开的构建实例的方法
Create(owner string) Product
// 实际生成实例的方法
createProduct(owner string) Product
// 保存已生成的实例
registerProduct(product Product)
}
接下来是产品接口Product,定义了两个方法,一个是获取产品持有人的方法GetOwner(),一个是模拟产品被使用的Use()方法
// 产品接口
type Product interface {
// 获取产品持有人名字
GetOwner() string
// 使用
Use()
}
实现
接下来是定义实现上面接口的具体类型,分别是实现Factory的IDCardFactory,以及实现Product的IDCard类型
IDCardFactory
// 身份证工厂,实现了Factory接口
type IDCardFactory struct {
products []Product `json:"products,omitempty"`
}
func (f *IDCardFactory) Create(owner string) Product {
idCard := f.createProduct(owner)
f.registerProduct(idCard)
return idCard
}
func (f *IDCardFactory) createProduct(owner string) Product {
return &IDCard{owner: owner}
}
func (f *IDCardFactory) registerProduct(idCard Product) {
f.products = append(f.products, idCard)
}
IDCard
// 身份证类型,实现了Product接口
type IDCard struct {
owner string `json:"owner,omitempty"`
}
func (c *IDCard) GetOwner() string {
return c.owner
}
func (c *IDCard) Use() {
fmt.Printf("使用了%s的身份证抢火车票!\n", c.owner)
}
测试
func main() {
var factory = &IDCardFactory{
products: make([]Product, 0), //golang在声明结构体时,不会为结构体内的字段申请内存空间
}
card1 := factory.Create("小明")
card1.Use()
card2 := factory.Create("小红")
card2.Use()
}
测试结果
代码已上传Github:LyonNee/design_patterns_with_go: 基于Golang实现的设计模式代码 (github.com)