golang 创立型设计模式 工厂方法
golang 创立型设计模式 工厂方法
缘起
最近复习设计模式
拜读谭勇德的<<设计模式就该这样学>>
该书以java语言演绎了常见设计模式
本系列笔记拟采用golang练习之
工厂方法
工厂方法模式(Factory Method Pattern)又叫作多态性工厂模式,指定义一个创立对象的接口,但由实现这个接口的类来决定实例化哪个类,工厂方法把类的实例化延迟到子类中进行。
在工厂方法模式中,不再由单一的工厂类生产产品,而是由工厂类的子类实现具体产品的创立。因而,当添加一个产品时,只要添加一个相应的工厂类的子类, 以处理简单工厂生产太多产品导致其内部代码臃肿(switch … case分支过多)的问题。
场景
- 某智能家居场景, 需要通过app统一控制智能照明灯的开关
- 智能灯可以打开 – Open(), 或者关闭 – Close()
- 智能灯可能来自不同厂商, 控制驱动不一样, 具体信息保存在配置文件中
- 当智能灯的品种越来越多以后, 简单工厂方法迅速膨胀, 变得难以维护, 因而需要改造为工厂方法
设计
- 定义ILight接口, 表示智能灯
- 定义ILightFactory接口, 表示创立智能灯的笼统工厂
- 定义LightInfo类, 保存不同灯的配置信息
- 定义FactoryRegistry类, 用于接受不同厂商的工厂子类
- 不同厂商各自实现笼统工厂和笼统产品
factory_method_test.go
单元测试
package patternsimport ( 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_FactoryMethodtMijiaLight.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)PASSok command-line-arguments 0.002sILight.go
定义智能灯的接口
package factory_methodtype ILight interface { ID() int Name() string Open() error Close() error}ILightFactory.go
定义智能灯工厂的接口
package factory_methodtype ILightFactory interface { Create(info *LightInfo) (error, ILight)}_
LightInfo.go
封装智能灯的配置信息
package factory_methodtype 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}FactoryRegistry.go
提供从厂商名称到该厂商的智能灯工厂实例的注册表
package factory_methodvar 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}MijiaLightFactory.go
位于”mijia”子目录, 实现ILightFactory接口, 提供对”mijia”产品的创立
package mijiaimport (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)}MijiaLight.go
位于”mijia”子目录, 实现ILight接口, 提供对”mijia”智能灯的实现
package mijiaimport "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}RedmiLightFactory.go
位于”redmi”子目录, 实现ILightFactory接口, 提供对”redmi”产品的创立
package redmiimport (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)}RedmiLight.go
位于”redmi”子目录, 实现ILight接口, 提供对”redmi”智能灯的实现
package redmiimport "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)笼统产品只能生产一种产品,此弊端可使用笼统工厂模式处理。
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » golang 创立型设计模式 工厂方法
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » golang 创立型设计模式 工厂方法