范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

工厂方法演进

  最近review代码,感觉工厂方法使用的不准确,正好以此为例聊一下工厂方法的演进。   实例初始需求
  假设我们有一个需求,需要根据不同的信号做不同的事情,如做饭、吃饭。
  在此需求基础上,我们用Go实现比较简单,使用经典的简单工厂即可:   创建一个interface,包含参数检查、执行动作   创建做饭、吃饭类,实现interface中的两个函数
  因为信号不同行为不同,根据查表法与switch有什么区别?,为后期扩展方便,我们选择switch方式。   需求进化
  后面我们发现需求变了,要增加洗碗、拖地,而且这两个的操作和做饭也很相似。
  这种情况下我们可以选择的方案有:   复用做饭类,在里面通过if判断是洗碗还是拖地   做饭、吃饭、洗碗、拖地完全独立,相互之间没有交集
  我们肯定选择方案2,使用下面两个技巧使代码高内聚、低耦合   使用基类:如洗碗、拖地都需要用水清扫,这些相同操作,在基类中实现,洗碗、拖地类继承基类   提取公因子,将各个类共同的功能放到框架中,如在做之前都吼了一嗓子,"我不想工作"   简单工厂实现
  关于工厂模式,大家可以看一下我的这篇文章Go设计模式(7)-工厂模式。简单工厂方法的UML图如下:
  对于初始需求的代码实现如下所示:   package main import "fmt" /**  * @Author: Jason Pang  * @Description:  */ type Life interface { 	CheckParams() error //参数检查 	Do() error          //执行动作 } type Cook struct { } /**  * @Author: Jason Pang  * @Description: 做饭参数检查  * @receiver c  * @return error  */ func (c *Cook) CheckParams() error { 	fmt.Println("cook 检查参数,食材准备完毕") 	return nil } /**  * @Author: Jason Pang  * @Description: 开始做饭  * @receiver c  * @return error  */ func (c *Cook) Do() error { 	fmt.Println("不想工作") 	fmt.Println("开始做饭") 	return nil } type Eat struct { } /**  * @Author: Jason Pang  * @Description: 吃饭参数检查  * @receiver c  * @return error  */ func (c *Eat) CheckParams() error { 	fmt.Println("eat 检查参数,饭已做好,碗筷放好") 	return nil } /**  * @Author: Jason Pang  * @Description: 开始吃饭  * @receiver c  * @return error  */ func (c *Eat) Do() error { 	fmt.Println("不想工作") 	fmt.Println("开始吃饭") 	return nil } /**  * @Description: 简单工厂  */ type Factory struct { } func (simple *Factory) create(ext string) Life { 	switch ext { 	case "cook": 		return &Cook{} 	case "eat": 		return &Eat{} 	} 	return nil } func main() { 	//简单工厂使用代码 	fmt.Println("------------简单工厂") 	factory := &Factory{} 	life := factory.create("cook") 	if life != nil { 		life.CheckParams() 		life.Do() 	} } 简单工厂演进实现
  需求演变之后,代码实现如下:   package main import "fmt" /**  * @Author: Jason Pang  * @Description:  */ type Life interface { 	CheckParams() error //参数检查 	Do() error          //执行动作 } /**  * @Author: Jason Pang  * @Description: 基类  */ type BaseLife struct { } /**  * @Author: Jason Pang  * @Description: 参数检查  * @receiver c  * @return error  */ func (c *BaseLife) CheckParams() error { 	fmt.Println("通用参数检查") 	return nil } /**  * @Author: Jason Pang  * @Description: 开始做饭  * @receiver c  * @return error  */ func (c *BaseLife) Do() error { 	fmt.Println("用水处理") 	return nil } type Cook struct { } /**  * @Author: Jason Pang  * @Description: 做饭参数检查  * @receiver c  * @return error  */ func (c *Cook) CheckParams() error { 	fmt.Println("cook 检查参数,食材准备完毕") 	return nil } /**  * @Author: Jason Pang  * @Description: 开始做饭  * @receiver c  * @return error  */ func (c *Cook) Do() error { 	fmt.Println("开始做饭") 	return nil } type Eat struct { } /**  * @Author: Jason Pang  * @Description: 吃饭参数检查  * @receiver c  * @return error  */ func (c *Eat) CheckParams() error { 	fmt.Println("eat 检查参数,饭已做好,碗筷放好") 	return nil } /**  * @Author: Jason Pang  * @Description: 开始吃饭  * @receiver c  * @return error  */ func (c *Eat) Do() error { 	fmt.Println("开始吃饭") 	return nil } /**  * @Author: Jason Pang  * @Description: 洗碗  */ type Wash struct { 	BaseLife } type Mop struct { 	BaseLife } func (c *Mop) CheckParams() error { 	fmt.Println("mop 检查参数,拖把是否存在") 	return nil } /**  * @Description: 简单工厂  */ type Factory struct { } func (simple *Factory) create(ext string) Life { 	switch ext { 	case "cook": 		return &Cook{} 	case "eat": 		return &Eat{} 	case "wash": 		return &Wash{} 	case "mop": 		return &Mop{} 	} 	return nil } func EchoBeforeDo() { 	fmt.Println("不想工作") } func main() { 	//简单工厂使用代码 	fmt.Println("------------简单工厂") 	factory := &Factory{} 	life := factory.create("mop") 	if life != nil { 		life.CheckParams() 		EchoBeforeDo() 		life.Do() 	} }
  输出:   ➜  myproject go run main.go ------------简单工厂 cook 检查参数,食材准备完毕 不想工作 开始做饭 ➜  myproject go run main.go ------------简单工厂 eat 检查参数,饭已做好,碗筷放好 不想工作 开始吃饭 ➜  myproject go run main.go ------------简单工厂 通用参数检查 不想工作 用水处理 ➜  myproject go run main.go ------------简单工厂 mop 检查参数,拖把是否存在 不想工作 用水处理
  大家可以看到,  这种方案即保证了各个操作之间的独立,又复用了共同代码(通过基类和提取公因子)。   总结
  使用工厂方法,有两个检验标准   具体产品类不应该相互之间关联   产品类里也不应该有相同的代码
  随着对业务的理解,区分出变与不变的内容,不变的内容需要整合到框架中,不应该在各个产品类里。
  产品类只需关注自己的逻辑,按照接口要求处理输入和返回值。这样今后即使有新功能接入,开发者也不需要关心整体框架,上手速度快、出问题的概率低。
  如果有默认的逻辑操作能跑通整个流程,最好有一个基类实现这个逻辑,这样就能最大程度的进行复用。
  开发过程中需要随着业务的变化和自己对业务的理解不断重构代码,这样才能让代码不成为屎山。但很多同学可能不敢重构,怕引起更多问题。其实这就和单元测试、自动化测试等关联起来了,只要质量保障的好,才能更放心的修改。我认为质量保障就是内功了,需要不断的坚持、不松懈,需要团队有很强的执行力,这是很难短时间被学去的,这便是护城河。
  代码位置:https://github.com/shidawuhen/asap/blob/master/controller/design/factory.go   最后
  大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)
  我的个人博客为:https://shidawuhen.github.io/
  往期文章回顾:   设计模式   招聘   思考   存储   算法系列   读书笔记   小工具   架构   网络   Go语言

铁道游击队中队长的原型是谁,建国后被授予了什么军衔?抗日战争时期,在山东曾经活跃着一支令日伪军闻风丧胆的敌后武装力量铁道游击队。游击队的战士们出没在敌人的铁路大动脉,熟练地扒火车,抢夺敌人的物资,破坏敌人的各种后勤补给,搜集敌人的各新四军第七师有多富裕?可养活20个甲级师,年均上缴20万两黄金冲天香阵透长安,满城尽带黄金甲。人类会为了追求极端的利益和财富而发动战争,但战争本身就犹如是一个需要不断往内添加燃料的冰冷机器,有的国家通过战场一跃成为了世界顶端的强国,有的国家却海外双11牵手世界杯,速卖通商家的逆袭时刻出海专题20202021年,受地缘以及疫情黑天鹅影响,中国创业者出海无疑正在经历前所未有之新变局。时针已经拨进2022年,他们目前的境况如何?有哪些经验和教训值得分享?出海未来是否还有机会全新宝马iX3上市,是在为降价作准备吗?事到如今,虽然新能源汽车免征购置税的政策继续延续至2023年12月31日,政策给力,市场潜力大,但是新能源汽车的体量是无论如何也不能和燃油车相提并论的,毕竟时间有限,拔苗助长的弊端4。4亿年前鱼类化石揭示有颌脊椎动物的崛起新华社北京9月28日电(记者张泉)我国科学家近期在重庆贵州等地约4。4亿年前的志留纪早期地层中发现重庆特异埋藏化石库和贵州石阡化石库,首次为有颌脊椎动物的崛起与最早期辐射分化提供了福布斯美国富豪榜马斯克挤下贝佐斯首夺冠美国知名财经杂志福布斯27日公布美国前400大富豪排行榜,特斯拉首席执行员马斯克首次夺冠,挤下亚马逊首席执行员贝佐斯面子书母公司Meta首席执行员朱克伯格则掉出前10名之外。据福布分布式数据库技术前瞻背景介绍在业务逐渐增长的4年多里,我公司的的数据库经历了从单表数十GB到上百GB的过程。基于数据量的升级变迁,我们的数据库也经历了2次架构迭代,并在探索三代数据库架构第一代数据库架法新社谷歌聚集顶尖科学家研发量子计算机吸引大量人才和投资中国小康网9月29日讯老马室外,温暖的九月阳光温暖了田园诗般的海岸,加利福尼亚又迎来了完美的一天。谷歌在圣巴巴拉的实验室拥有大约20台量子计算机法新社报道,在建筑内部,某些地方的温院士是博导是一种怎样的体验?分分钟起飞博士本就是万里挑一,若能成为院士的博士更是光宗耀祖,能有一个院士的博导,好处当然是大大的!首先,有院士当导师,本身就进去了普通人难以触及的更高圈层。我国的院士头衔,基本就是中国科学iPhone14Pro全网首摔,被天价维修费惊呆,网友摔不起声明原创不易,禁止搬运,违者必究!iphone14系列发布后,可以说更多的用户将关注度放在了Pro机型上。因为今年的iphone14,只有Pro机型有比较明显的提升,不过价格也比较中国新能源目前发展的水平,包括新能源汽车光伏风电储能等新能源包括新能源汽车光伏风电储能氢能水电核能生物质能,中国在新能源领域很多都是世界第一,跟能源结构有关系,自然资源富煤缺油少气,70以上的原油需要进口,基本上走海运,一单被美国印度
为什么有人说老小区的房子不能买?老小区一般是指2000年以前开发建设的住宅小区,这些住宅小区都有以下特点一是岁数大,这样的住宅小区,房龄都在二十年以上,有的高达三四十年。二是缺乏整体规划设计,由于当时对城市规划统退休老两口准备去成都玩一个月大概需要多少钱?退休老俩口休闲游选择成都是非常明智的。我作为老成都人,可以给你一份最靠谱的预算清单。到一个城市旅行,费用主要是由出发城市到目的地的大交通费用食宿费用往返各景区景点交通费用以及门票构教师的工资提高到每月多少钱才算合理呢?对于一个国家来说,教育乃立国之本!有句话叫做,教师是人类灵魂的工程师。可见教师这一职业对人类发展的贡献!教育是一个良心事业,因为教师教育的是一代代的小孩子,而小孩子将来长大了就会影个体户一年交一万多社保,交满十五年以后一个月能领多少钱?你好!个体户一年交一万多元社保,交满十五年以后,一个月能领多少钱?从题主的介绍来看,你是按年缴费,一年缴纳社保一万多元,所以可以看得出你参加的是城乡居民养老保险。城乡居民保险的养老迈腾与宝马3系,哪个空间比较大?我是320Li和蔚揽(迈腾B8旅行版)车主,对3系和迈腾的空间自认算是比较了解的。迈腾是欧版Passat的加长款,代号B8L,所以比空间的话,就拿3系Li来说了。先说后排吧,我个人现在福特汽车值得买吗?不捧不喷,实事求是作答!一,如果你在网络上问这句话,肯定得到的大多数结果都是不建议购买,因为福特已经给不出高额的广宣费用了。二,福特在中国市场有过辉煌,但有如昙花一现。原因出在高层听说声波牙刷刷一次等于传统刷牙刷一个月的清洁程度是真的吗?电动牙刷vs手动牙刷理论上的比较震动频率电动牙刷主要分为两种,一种是被称为电动牙刷,一种是声波牙刷。电动牙刷已经有了60多年的使用历史了,震动刷头通常频率在25007000次每分钟保养贵油耗高故障多,日系车法系车德系车美系车国产车,有哪些车不能触碰?逐个盘点一下各车系的优缺点和问题车型,大家避免踩坑。法系全系都没有什么过硬的产品,标志雪铁龙和雷诺,基本上都快要或者已经退出中国市场了。不说车好坏,日后你车买了,还没脱保,他们拍拍三百元以内的高性价比白酒有哪些?不知道是不是经常喝的原因,我有老家是山东的朋友,自从来贵州上班后,刚开始也是觉得贵州产的酱香型白酒又苦又辣不好喝,慢慢的因为我们这面很多人喝的都是酱香型酒,而且又是国酒茅台的产地,我想买个汽车,分期付款好呢还是一次付清好呢?对于全款买车还是贷款买车好这个问题,每个人都是实际情况,也有取所需,没有绝对的好坏,只是看个人实际情况,我个人建议如果能全款买下还是全款买车,为什么呢?我分析一下我的情况,我以前买长城吉利奇瑞比亚迪谁的底盘技术更强?长城吉利奇瑞比亚迪谁的底盘技术更强?对比一下就知道了!我们在谈论三大件的技术实力的时候,很少对比底盘技术,因为一方面,底盘的好坏没有明确的参数来衡量,往往要深度试驾之后,才能感受到