最近复习设计模式
拜读谭勇德的<<设计模式就该这样学>>
该书以java语言演绎了常见设计模式
本系列笔记拟采用golang练习之java
工厂方法模式(Factory Method Pattern)又叫做多态性工厂模式,指定义一个建立对象的接口,但由实现这个接口的类来决定实例化哪一个类,工厂方法把类的实例化推迟到子类中进行。
在工厂方法模式中,再也不由单一的工厂类生产产品,而是由工厂类的子类实现具体产品的建立。所以,当增长一个产品时,只需增长一个相应的工厂类的子类, 以_解决简单工厂生产太多产品致使其内部代码臃肿(switch … case分支过多)的问题_。golang
单元测试设计模式
package patterns import ( fm "learning/gooop/creational_patterns/factory_method" "testing" // 引入mijia并自动注册 _ "learning/gooop/creational_patterns/factory_method/mijia" // 引入redmi并自动注册 _ "learning/gooop/creational_patterns/factory_method/redmi" ) func Test_FactoryMethod(t *testing.T) { config := make([]*fm.LightInfo, 0) config = append(config, fm.NewLightInfo(1, "客厅灯", "mijia", "L-100")) config = append(config, fm.NewLightInfo(2, "餐厅灯", "redmi", "L-45")) for _,info := range config { factory := fm.DefaultFactoryRegistry.Get(info.Vendor()) if factory == nil { t.Errorf("unsupported vendor: %s", info.Vendor()) } else { e, light := factory.Create(info) if e != nil { t.Error(e.Error()) } else { _ = light.Open() _ = light.Close() } } } }
$ go test -v factory_method_test.go === RUN Test_FactoryMethod tMijiaLight.open, &{1 客厅灯 mijia L-100} tMijiaLight.Close, &{1 客厅灯 mijia L-100} tRedmiLight.open, &{2 餐厅灯 redmi L-45} tRedmiLight.Close, &{2 餐厅灯 redmi L-45} --- PASS: Test_FactoryMethod (0.00s) PASS ok command-line-arguments 0.002s
定义智能灯的接口app
package factory_method type ILight interface { ID() int Name() string Open() error Close() error }
定义智能灯工厂的接口框架
package factory_method type ILightFactory interface { Create(info *LightInfo) (error, ILight) }
_oop
封装智能灯的配置信息单元测试
package factory_method type LightInfo struct { iID int sName string sVendor string sModel string } func NewLightInfo(id int, name string, vendor string, model string) *LightInfo { return &LightInfo{ id, name, vendor, model, } } func (me *LightInfo) ID() int { return me.iID } func (me *LightInfo) Name() string { return me.sName } func (me *LightInfo) Vendor() string { return me.sVendor }
提供从厂商名称到该厂商的智能灯工厂实例的注册表测试
package factory_method var DefaultFactoryRegistry = newFactoryRegistry() type IFactoryRegistry interface { Set(vendor string, factory ILightFactory) Get(vendor string) ILightFactory } type tSimpleFactoryRegistry struct { mFactoryMap map[string]ILightFactory } func newFactoryRegistry() IFactoryRegistry { return &tSimpleFactoryRegistry{ mFactoryMap: make(map[string]ILightFactory, 0), } } func (me *tSimpleFactoryRegistry) Set(vendor string, factory ILightFactory) { me.mFactoryMap[vendor] = factory } func (me *tSimpleFactoryRegistry) Get(vendor string) ILightFactory { it,ok := me.mFactoryMap[vendor] if ok { return it } return nil }
位于"mijia"子目录, 实现ILightFactory接口, 提供对"mijia"产品的建立设计
package mijia import (fm "learning/gooop/creational_patterns/factory_method") func init() { fm.DefaultFactoryRegistry.Set("mijia", newMijiaLightFactory()) } type tMijiaLightFactory struct { } func newMijiaLightFactory() fm.ILightFactory { return &tMijiaLightFactory{} } func (me *tMijiaLightFactory) Create(info *fm.LightInfo) (error, fm.ILight) { return nil, NewMijiaLight(info) }
位于"mijia"子目录, 实现ILight接口, 提供对"mijia"智能灯的实现code
package mijia import "fmt" import (fm "learning/gooop/creational_patterns/factory_method") type tMijiaLight struct { fm.LightInfo } func NewMijiaLight(info *fm.LightInfo) *tMijiaLight { return &tMijiaLight{ *info, } } func (me *tMijiaLight) Open() error { fmt.Printf("tMijiaLight.open, %v\n", &me.LightInfo) return nil } func (me *tMijiaLight) Close() error { fmt.Printf("tMijiaLight.Close, %v\n", &me.LightInfo) return nil }
位于"redmi"子目录, 实现ILightFactory接口, 提供对"redmi"产品的建立
package redmi import (fm "learning/gooop/creational_patterns/factory_method") func init() { fm.DefaultFactoryRegistry.Set("redmi", newRedmiLightFactory()) } type tRedmiLightFactory struct { } func newRedmiLightFactory() fm.ILightFactory { return &tRedmiLightFactory{} } func (me *tRedmiLightFactory) Create(info *fm.LightInfo) (error, fm.ILight) { return nil, newRedmiLight(info) }
位于"redmi"子目录, 实现ILight接口, 提供对"redmi"智能灯的实现
package redmi import "fmt" import (fm "learning/gooop/creational_patterns/factory_method") type tRedmiLight struct { fm.LightInfo } func newRedmiLight(info *fm.LightInfo) *tRedmiLight { return &tRedmiLight{ *info, } } func (me *tRedmiLight) Open() error { fmt.Printf("tRedmiLight.open, %v\n", &me.LightInfo) return nil } func (me *tRedmiLight) Close() error { fmt.Printf("tRedmiLight.Close, %v\n", &me.LightInfo) return nil }
工厂方法模式的优势
(1)灵活性加强,对于新产品的建立,只需多写一个相应的工厂类。
(2)典型的解耦框架。高层模块只须要知道产品的抽象类,无须关心其余实现类,知足迪米特法则、依赖倒置原则和里氏替换原则。
工厂方法模式的缺点
(1)类的个数容易过多,增长复杂度。
(2)增长了系统的抽象性和理解难度。
(3)抽象产品只能生产一种产品,此弊端可以使用抽象工厂模式解决。