内容:记录工厂模式的学习
工厂模式:
概念:
工厂模式(Factory Pattern)是常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了
一种创建对象的最佳方式。
特点:
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。
注意事项:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是
复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。
如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
作用:
工厂模式是为了解耦:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只调用B的方法,
而至于B的实例化,就交给工厂类。
优点:
1、工厂模式可以降低代码重复。如果创建对象的过程都很复杂,需要一定的代码量,而且很多地方都用到,那就会
有很多的重复代码。我们可以这些创建对象的代码放到工厂里统一管理。既减少了重复代码,也方便以后对对象的
创建过程的修改维护。
2、由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象的地方去逐个修正,
只需要在工厂里修改即可,降低维护成本。同理,想把所有调用某对象的地方改成其子类,只需要在对应生产此
对象的工厂中或者工厂的方法中修改其生产的对象为其子类即可即可,而不需要找到所有的生产此对象的语句。
也就是不需要做:new x() -----> new x-son()
3、工厂管理了对象的创建逻辑,使用者并不需要知道具体的创建过程,只管使用即可,减少了使用者因为不了解
对象细节,而出现的创建逻辑出错,而导致的错误。
工厂模式的演变一:简单工厂模式
type API interface {
do(name string) string
}
//这个是工厂函数,返回一个interface
func NewAPI(t int) API {
if t == 1 {
return &do1{}
} else if t == 2 {
return &do2{}
}
return nil
}
//这个是一个具体的类型,do1
type do1 struct{}
func (*do1) do(name string) string {
return fmt.Sprintf("start do: %s", name)
}
//这是一个具体的类型,do2
type do2 struct {
}
func (*do2) do(name string) string {
return fmt.Sprintf("start do: %s", name)
}
使用代码:
func Test(t *testing.T) {
api := NewAPI(1)
s := api.do("create!")
}
缺点:
简单工厂模式在增加一个新的类型时,除了要增加新的类和方法之外,还需要修改工厂函数,在工厂函数中
添加case,这一点违背了对修改关闭这个原则(开放-封闭原则),所以需要进一步解耦
工厂模式的演变二:进阶工厂模式
package factoryCreate
type Operator interface {
SetA(int)
SetB(int)
Result() int
}
type OperatorFactory interface {
Create() Operator
}
type OperatorBase struct {
a, b int
}
//set A
func (o *OperatorBase) SetA(a int) {
o.a = a
}
//SetB
func (o *OperatorBase) SetB(b int) {
o.b = b
}
//这里还创建一个新的加法工厂类,这个依赖于下面的具体加法类
type PlusOperatorFactory struct {
}
//这个类实现了这个方法之后,不但可以让这个类的实例赋值给OperatorFactory
//还可以通过这个函数创建加法实际操作的实例-PlusOperator类型的实例
func (PlusOperatorFactory) Create() Operator {
return &PlusOperator{
OperatorBase: &OperatorBase{},
}
}
//具体的加法类
type PlusOperator struct {
*OperatorBase
}
func (o PlusOperator) Result() int {
return o.a + o.b
}
//减法工厂类,依赖于下面的具体减法类
type MinusOperatorFactory struct{}
func (MinusOperatorFactory) Create() Operator {
return &MinusOperator{
OperatorBase: &OperatorBase{},
}
}
//具体的减法类
type MinusOperator struct {
*OperatorBase
}
func (o MinusOperator) Result() int {
return o.a - o.b
}
//使用代码:
func compute(factory OperatorFactory, a, b int) int {
op := factory.Create()
op.SetA(a)
op.SetB(b)
return op.Result()
}
func Test(t *testing.T) {
var (
factory OperatorFactory
)
factory = PlusOperatorFactory{} //使用具体操作类
if compute(factory, 1, 2) != 3 {
t.Error("error with factory method pattern")
}
factory = MinusOperatorFactory{} //使用具体操作类
if compute(factory, 4, 2) != 2 {
t.Fatal("error with factory method pattern")
}
}
进阶工厂模式在新增具体类时,不需要去修改原有工厂结构。还有缺陷:
如果我们需要修改operator中的方法时,那么需要修改的地方还是挺多
工厂模式的演变三:抽象工厂模式
//以电子设备生产为例子:
func main() {
factory := new(LenovoFactory) //工厂是生产联想产品线的
pc := factory.ProducePC()
phone := factory.ProducePhone()
pc.Compute()
phone.Telecom()
}
//定义产品的接口(电脑)
type IPC interface {
Compute()
}
//定义产品的接口(手机)
type IPhone interface {
Telecom()
}
//定义一个抽象工厂
type IFactory interface {
ProducePC() IPC
ProducePhone() IPhone
}
//定义一个具体电脑工厂,工厂实现类
type LenovoFactory struct {
}
func (factory *LenovoFactory) ProducePC() IPC {
return &LenovoPC{"Lenovo"}
}
func (factory *LenovoFactory) ProducePhone() IPhone {
return &LenovoPhone{"Lenovo"}
}
//定义一个联想电脑,产品实现类 ,具体产品
type LenovoPC struct {
Label string
}
func (pc *LenovoPC) Compute() {
//do compute
}
//定义一个联想手机,产品实现类 ,具体产品
type LenovoPhone struct {
Label string
}
func (phone *LenovoPhone) Telecom() {
//do telecom
}
在原来的基础上又多了一层解耦,与演变二对比,就是相当于又工厂生产了一个抽象操作类,操作类再去实现具体操作类,然后具体方法在具体操作类中,不在抽象操作类中