百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

工厂制造细节无须知——大佬对于工厂方法模式全方面的讲解

yuyutoo 2024-10-15 17:01 37 浏览 0 评论

1 需要了解工厂制造细节吗?

时间:3月19日22点  地点:小菜、大鸟住所的客厅  人物:小菜、大鸟

小菜来找大鸟,说:"简单工厂模式真是很好用呀,我最近好几处代码都用到了该模式。"

"哦!"大鸟淡淡地说道,"简单工厂只是最基本的创建实例相关的设计模式。但真实情况中,有更多复杂的情况需要处理。简单工厂生成实例的类,知道了太多的细节,这就导致这个类很容易出现难维护、灵活性差问题,让人感觉到了不好的味道。"

"知道很多细节不太好吗?"

"现实中,我们要想过好生活,是不太需要也不太可能知道所有细节的。比如说,我们知道猪长什么样子,也知道红烧肉很好吃,但一头猪是通过怎么样的过程变成红烧肉的呢?养殖、运输、屠宰、销售过程的批发、零售,还有饭店或家里的烹饪过程,对我们来说,都是不需要去了解的。我们去饭店吃饭,只要点了红烧肉,过一会儿它就被送出来了,好吃就行了,你说对不对?"

"将来如果能生产出这样一台机器,送进去是猪,出来就是红烧肉,那就好了。"

"嘿嘿!这样的机器我不知道是否生产得出来。不过,整个过程也算是一种封装吧。在我们的程序中,确实存在封装实例创建过程的模式——工厂方法模式,这个模式可以让创建实例的过程封装到工厂类中,避免耦合。它与简单工厂模式是一个体系的,你可以去研究一下。"

2 简单工厂模式实现

"大鸟!我研究了工厂方法模式,但还是不太理解它和简单工厂的区别,感觉还不如简单工厂方便,为什么要用这个模式?到底这个模式的精髓在哪里?"

"那你先把简单工厂模式和工厂方法模式的典型实现说给我听听。"

"哦,简单工厂模式实现是这样的:首先简单工厂模式,若以我写的计算器为例,结构图如下。"

"工厂类是这样写的。"

"客户端的应用。"

3 工厂方法模式实现

"那么如果是换成工厂方法模式来写这个计算器,你能写吗?""当然是可以,就是因为我写出来了,才感觉好像工厂方法没什么好处!

计算器的工厂方法模式实现的结构图是这样的。"

"先构建一个工厂接口。"

"然后加减乘除各建一个具体工厂去实现这个接口。"

"在OperationFactory类中,可以是这样的。"

"对呀,写得很好。"大鸟说,"工厂方法模式就是这样写的,你有什么问题?"

4 简单工厂vs.工厂方法

"怪就怪在这里呀,以前我们不是说过,如果我现在需要增加其他运算,比如求x的n次方(x n),或者求a为底数b的对数(logab),这些功能的增加,在简单工厂里,我是先去加求x的n次方的指数运算类,然后去更改OperationFactory类,当中加'Case'语句来做判断。现在用了工厂方法,加指数运算类没问题,去改OperationFactory类的分支也没问题,但又增加了一个指数工厂类,这不等于不但没有降低难度,反而增加类,把复杂性增加了吗?为什么要这样?"

"问得好。简单工厂模式的最大优点在于工厂类中包含必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。就像你的计算器,让客户端不用管该用哪个类的实例,只需要把'+'给工厂,工厂自动就给出了相应的实例,客户端只要去做运算就可以了,不同的实例会实现不同的运算。但问题也就在这里,如你所说,如果要加一个'求x的n次方(xn)'的功能,我们需要给OperationFactory类的方法里加'Case'的分支条件。目前来看,这个OperationFactory类,承载了太多功能,这可不是好办法。这就等于说,我们不但对扩展开放了,对修改也开放了,这样就违背了什么原则?"

"哦,是的,违背的是开放-封闭原则。"

"对,也就是说,我们加减乘除运算的部分已经相当成熟了,但是因为增加新的功能,就要去改已经很成熟的类代码,这就好比很多鸡蛋放在了一个篮子里,这是很危险的。"

"那么工厂方法模式,就可以解决这个问题吗?我感觉我本来是4个运算类,1个工厂类,共5个类,现在多出了4个运算工厂类和1个工厂接口,问题依然没有解决。"

"哈哈,那是因为你没有真的理解工厂方法。举一个例子,我们公司本来只有一家工厂,生产四种不同的产品。后来发展得特别好,需要增加新的两种产品放在另一个地方开设新的工厂。新的工厂不应该影响原有工厂的正常工作,你说怎么办?"

"新工厂建在别的地方,应该不影响原有的工厂运作,最多就是建好后,总公司那里再增加一些协调管理部门就好了。"

"说得非常好。就编程来说,我们应该尽量将长的代码分派切割成小段,再将每一小段'封装'起来,减少每段代码之间的耦合,这样风险就分散了,需要修改或扩展的难度就降低了。加减乘除四个类算是一个工厂的产品,不妨叫它们(基础运算工厂)类,现在增加指数、对数运算类,如果算是另一种工厂的两种产品,不妨称它为'高级运算工厂'类,你觉得有必要去影响原有的基础运算工厂运作吗?"

"哦!我明白你的意思了。并不是要去创建加法工厂、减法工厂这样的类,而是将加减乘除用一个基础工厂来创建,现在增加了新的产品,又不想影响原有的工厂代码,于是就扩展一个新的工厂来处理。我马上改。"

"下面是原有的工厂结构,加减乘除运算已经非常稳定,尽量不要去改变它们。"

"增加了一种新的工厂和两种新的运算类(以后可以扩展更多的高级运算,比如正余弦、正余切等),不要影响原有的代码和运作。"

"增加两个运算类。"

"工厂接口不变。"

"基础运算工厂类,此类已经比较成熟稳定,实现后应该封装到位,不建议轻易修改。"

"高级运算工厂类,也许还有扩展产品的可能。"

"左侧新的OperationFactory类与右侧原来的OperationFactory类对比。"

"你或许会发现,新的OperationFactory类已经不存在运算子类实例化的代码了。也就是说,在这个代码里,全部是接口与具体工厂类,并不存在具体的实现,与原来的OperationFactory类对比,实例化的过程延迟到了工厂子类中。"大鸟说道,"不过新的OperationFactory类依然存在'坏味道',当增加新的运算子类时,它本身也是需要更改的,这个先放在一边,以后可以解决。"

"Perfect!我明白了。这就是前面提到的针对接口编程,不要对实现编程吧?"

"是的。我们来看工厂方法的定义。注意关键词——延迟到子类。"

工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。[DP

"我们讲过,既然这个工厂类与分支耦合,那么我就对它下手,根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口具体生成对象的工厂。每个工厂可以有多个不同产品,而工厂之间,又是相对隔离封装状态。这样过去已经比较完善的工厂和产品体系,就不需要再去改动它们,而另外需要变更的代码,完全可以通过扩展来变化,这就完全符合了开放-封闭原则的精神。"

"哦,工厂方法从这个角度讲,的确要比简单工厂模式来得强。"

"严格来说,是一种升级。当只有一个工厂时,就是简单工作模式,当有多个工厂时,就是工厂方法模式。类似由一维进化成了二维,更强大了。"

5 商场收银程序再再升级

大鸟:"还记得我们前面不断改进过的商场收银程序吗?最后一版是增加了装饰模式。"

小菜:"我记得。后面已经改得非常漂亮了,能适应各种变化。"

大鸟:"那你看看下面这段代码有优化的空间吗?"

小菜:"以前不觉得,现在发现确实是太多的new实例了,尤其是5和6,装饰模式的使用,在这个CashContext类中,显得特别的复杂。"

大鸟:"是的,那么学完了工厂方法模式,你有没有改进的想法?"

小菜:"我想想。你的意思是创建几个工厂类来处理这些new?"

大鸟:"问题是,你打算创建几个工厂类呢?"

小菜:"从上面的代码来看,我感觉至少应该有原价销售类、打折类、满减返利类、先打折再满减类和先满减再打折类,一共五个工厂类。"

大鸟:"尝试抽象一下,能不能合并一部分呢?"

小菜:"我想想。好像原价类,可以想象成打折的参数为1的打折类。但打折与满减返利好像合并不了。"

大鸟:"它俩是合并不了,但先打折后满减类能不能涵盖它们俩?"

小菜:"我懂了。如果有'先打折后满减类'存在,那它应该有三个初始化参数:折扣值、满减条件、满减返利值,那么打折类,其实就是满减返利值条件为0的情况,另外满减类,就相当于折扣参数为1的情况。"

大鸟:"非常好!所以最终只会抽象成几个工厂类?"

小菜:"那就只需要'先打折再满减'和'先满减再打折'两个工厂类了。"

大鸟:"赶紧去实现一下吧。"

6 简单工厂+策略+装饰+工厂方法

小菜:"我的实现方法,首先原有的ISaleCashSuperCashNormalCashReturnCashRebate等类都不变。""增加IFactory接口。"

"增加实现IFactory接口的两个类,'先打折再满减'类和'先满减再打折'类,其中红框部分代码为装饰模式的实现。"

"有了上面的这些准备后,CashContext类就简单多了,它针对的是ISale接口、IFactory接口编程,然后两个工厂类,对于各个打折满减算法CashSuperCashNormalCashReturnCashRebate等具体类一无所知。实现了松耦合的目的。"

大鸟向小菜竖起了大拇指。

小菜:"我感觉工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。"

大鸟:"说得好,它们都是集中封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合。工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。就像生活中,凡是在基层工作过的人都知道,具体事情做得越多,越容易犯错误。相反,如果做官做得高了,说出的话就会比较抽象、笼统,很多时候犯错误的可能性反而就越来越小了。"

小菜:"工厂方法模式是不是本质就是对获取对象过程的抽象?"

大鸟:"说得非常对,就是这样。工厂方法的好处有这么几条:第一,对于复杂的参数的构造对象,可以很好地对外层屏蔽代码的复杂性,注意是指创建新实例的构造对象。比如说我们用了'先打折再满减'类工厂,其实就屏蔽了装饰模式的一部分代码,让CashContext不再需要了解装饰的过程。第二,很好的解耦能力。这点刚才你也说了,这就是针对接口在编程。当我们要修改具体实现层的代码时,上层代码完全不了解实现层的情况,因此并不会影响到上层代码的调用,这就达到了解耦的目的。"

小菜:"对了。你说这还不是最佳的做法?那应该如何做呢?还有就是这样还是没有避免修改客户端的代码呀?"

大鸟:"哈,之前我就提到过,利用'反射'可以解决避免分支判断的问题。不过今天还是不急,等以后再谈。"

小菜:"好的好的。你饿了吗?我们要不去撸串吃点夜宵?"

大鸟:"走!去吃封装羊肉去。"

相关推荐

Python操作Word文档神器:python-docx库从入门到精通

Python操作Word文档神器:python-docx库从入门到精通动动小手,点击关注...

Python 函数调用从入门到精通:超详细定义解析与实战指南 附案例

一、函数基础:定义与调用的核心逻辑定义:函数是将重复或相关的代码块封装成可复用的单元,通过函数名和参数实现特定功能。它是Python模块化编程的基础,能提高代码复用性和可读性。定义语法:...

等这么长时间Python背记手册终于来了,入门到精通(视频400集)

本文毫无套路!真诚分享!前言:无论是学习任何一门语言,基础知识一定要扎实,基础功非常的重要,找一个有丰富编程经验的老师或者师兄带着你会少走很多弯路,你的进步速度也会快很多,无论我们学习的目的是什么,...

图解Python编程:从入门到精通系列教程(附全套速查表)

引言本系列教程展开讲解Python编程语言,Python是一门开源免费、通用型的脚本编程语言,它上手简单,功能强大,它也是互联网最热门的编程语言之一。Python生态丰富,库(模块)极其丰富,这使...

Python入门教程(非常详细)从零基础入门到精通,看完这一篇就够

本书是Python经典实例解析,采用基于实例的方法编写,每个实例都会解决具体的问题和难题。主要内容有:数字、字符串和元组,语句与语法,函数定义,列表、集、字典,用户输入和输出等内置数据结构,类和对象,...

Python函数全解析:从入门到精通,一文搞定!

1.为什么要用函数?函数的作用:封装代码,提高复用性,减少重复,提高可读性。...

Python中的单例模式:从入门到精通

Python中的单例模式:从入门到精通引言单例模式是一种常用的软件设计模式,它保证了一个类只有一个实例,并提供一个全局访问点。这种模式通常用于那些需要频繁创建和销毁的对象,比如日志对象、线程池、缓存等...

【Python王者归来】手把手教你,Python从入门到精通!

用800个程序实例、5万行代码手把手教你,Python从入门到精通!...

Python从零基础入门到精通:一个月就够了

如果想从零基础到入门,能够全职学习(自学),那么一个月足够了。...

Python 从入门到精通:一个月就够了

要知道,一个月是一段很长的时间。如果每天坚持用6-7小时来做一件事,你会有意想不到的收获。作为初学者,第一个月的月目标应该是这样的:熟悉基本概念(变量,条件,列表,循环,函数)练习超过30个编...

Python零基础到精通,这8个入门技巧让你少走弯路,7天速通编程!

Python学习就像玩积木,从最基础的块开始,一步步搭建出复杂的作品。我记得刚开始学Python时也是一头雾水,走了不少弯路。现在回头看,其实掌握几个核心概念,就能快速入门这门编程语言。来聊聊怎么用最...

神仙级python入门教程(非常详细),从0到精通,从看这篇开始!

python入门虽然简单,很多新手依然卡在基础安装阶段,大部分教程对一些基础内容都是一带而过,好多新手朋友,对一些基础知识常常一知半解,需要在网上查询很久。...

Python类从入门到精通,一篇就够!

一、Python类是什么?大家在生活中应该都见过汽车吧,每一辆真实存在、能在路上跑的汽车,都可以看作是一个“对象”。那这些汽车是怎么生产出来的呢?其实,在生产之前,汽车公司都会先设计一个详细的蓝图...

学习Python从入门到精通:30天足够了,这才是python基础的天花板

当年2w买的全套python教程用不着了,现在送给有缘人,不要钱,一个月教你从入门到精通1、本套视频共487集,本套视频共分4季...

30天Python 入门到精通(3天学会python)

以下是一个为期30天的Python入门到精通学习课程,专为零基础新手设计。课程从基础语法开始,逐步深入到面向对象编程、数据处理,最后实现运行简单的大语言模型(如基于HuggingFace...

取消回复欢迎 发表评论: