1. 问题引出

当使用到“new”,就会想到“具体”

简单工厂模式,工厂方法模式和抽象工厂模式。

2. 找出会变化的部分,把它们从不变部分分离出来

简单工厂模式,工厂方法模式和抽象工厂模式。

但是如果需要更多地比萨类型

简单工厂模式,工厂方法模式和抽象工厂模式。

看见了吗,根据比萨的类型,我们实例化正确的具体类。

如果呢?我们需要添加Clam Pizza和Veggie Pizza比萨类型,我们也要将这些风味加入我们的菜单,同时删除一些卖的不好的比萨

简单工厂模式,工厂方法模式和抽象工厂模式。

很明显的,如果实例化“某些具体类”,将不断地修改orderPizza,导致无法对修改关闭,所以此时我们已经知道了,哪些会改变,哪些不会改变,该是使用封装的时候了。

3. 封装创建对象的代码

简单工厂模式,工厂方法模式和抽象工厂模式。

我们将上面这部分代码,封装到另一个对象中,这个新对象只管如何创建比萨。

我们称这个对象为“工厂”,orderPizza()就变成了此“工厂”的客户。

4. 建立一个简单的比萨工厂

简单工厂模式,工厂方法模式和抽象工厂模式。

 

这样做的好处: 代码复用,不光orderPizza()方法可以成为客户,其他类也能成为客户;

1. 工厂可以设置为静态的类,因为其实并不需要创建对象来调用工厂方法。

5. 重写PizzaStore类

简单工厂模式,工厂方法模式和抽象工厂模式。

6. 这就是简单工厂

上面所使用的套路不是一个设计模式,其实是一种编程习惯而已,称之为“简单工厂”,请记住:这不是工厂模式。

7. 加盟比萨店

简单工厂模式,工厂方法模式和抽象工厂模式。

问题:如果想要多一些质量控制,比如说:加盟店采用工厂创建比萨,但是其他部分采用他们自创的流程:流程有些地方有些差异。

所以呢,我们希望建立一个框架,把加盟店和创建比萨捆绑在一起的同时又保持一定的弹性。

将createPizza()放入PizzaStore类中

简单工厂模式,工厂方法模式和抽象工厂模式。

8. 允许子类做决定

我们让各个地区的pizza店继承PizzaStore,实现createPizza方法,这样可以简单地说由子类各自决定如何制造比萨。下面是实现的类图

简单工厂模式,工厂方法模式和抽象工厂模式。

子类如何做决定:orderPizza调用createPizza时,某个比萨店子类将负责创建比萨。做哪一种比萨,当然由具体的比萨店来做决定。严格来说,是顾客决定。

工厂方法:抽象,必须返回一个产品,可以需要参数也可以不需要。

简单工厂模式,工厂方法模式和抽象工厂模式。

我们来实现比萨本身:

简单工厂模式,工厂方法模式和抽象工厂模式。

简单工厂模式,工厂方法模式和抽象工厂模式。

9.认识工厂方法模式

重点:所有的工厂模式都用来封装对象的创建。

简单工厂模式,工厂方法模式和抽象工厂模式。

另一个观点,它们是平行的类层级

简单工厂模式,工厂方法模式和抽象工厂模式。

下面是工厂方法通用结构

简单工厂模式,工厂方法模式和抽象工厂模式。

问题:当有一个concreteCreator的时候,工厂方法模式有什么优点?

尽管只有一个具体创建者,工厂方法依然很有用,因为它帮助我们将产品的“实现”从“使用”中解耦,如果增加产品或者改变产品的实现,creator并不会收到影响,因为它们不是紧耦合。

问题:如果说纽约和芝加哥的商店是利用简单工厂创建的,这样说是否正确?

不对啊,因为创建的方法是商店扩展自一个类,而简单工厂是另外单独的一个类的方法去创建对象。

问题:简单工厂和工厂方法之间的差异,我依然感到困惑。他们看起来很类似,差别在于,在工厂方法中,返回比萨的类是子类,能解释一下吗?

子类的确看上去很像简单工厂,简单工厂把全部事情在一个地方处理完了,然后工厂方法是创建一个框架,让子类决定要如何实现。比方说,orderPizza方法依赖工厂方法创建具体类,并制造出的比萨是什么?可通过继承PizzaStore类,决定实际制造出比萨是什么?简单工厂的做法,可以将对象的创建封装起来,简单工厂不具备工厂方法的弹性,简单工厂不能变更正在创建的产品。

10. 看看对象依赖

简单工厂模式,工厂方法模式和抽象工厂模式。

设计原则(依赖倒置原则):要依赖抽象,不要依赖具体类。

简单工厂模式,工厂方法模式和抽象工厂模式。

倒置思维方式如下

简单工厂模式,工厂方法模式和抽象工厂模式。

下面三个指导方针帮助我们遵循此原则:

1. 变量不可以持有具体类的引用:如果使用new,order方法会持有具体类的引用,我们利用工厂来避开这样的做法;

2. 不要让类派生自具体类:如果派生自具体类,就会依赖具体类,请派生自一个抽象(接口或抽象类);

3. 不要覆盖基类中已经实现的方法:如果覆盖已经实现的方法,那么你的基类不是一个真正被继承的抽象,基类中已实现的方法,应该由所有子类共享。

11. 再回到比萨店

简单工厂模式,工厂方法模式和抽象工厂模式。

12. 原料家族

纽约使用一组原料,芝加哥使用另一组原料等等(出现了和比萨一样的问题)

简单工厂模式,工厂方法模式和抽象工厂模式。

基于此,我们创建原料工厂,也就是一个工厂加若干个不同地区工厂的子类。

简单工厂模式,工厂方法模式和抽象工厂模式。

简单工厂模式,工厂方法模式和抽象工厂模式。

我们重做比萨,prepare声明为抽象的,方便不同的比萨采用不同的原料。

简单工厂模式,工厂方法模式和抽象工厂模式。

我们实现比萨的一个子类

简单工厂模式,工厂方法模式和抽象工厂模式。

所以,比萨利用相关工厂生产原料,比萨只使用原料,不管如何实现原料,所以比萨和原料之间被解耦。

简单工厂模式,工厂方法模式和抽象工厂模式。

再回到纽约的比萨店,看看我们和具体的工厂连上线了

简单工厂模式,工厂方法模式和抽象工厂模式。

13. 基于以上我们做了些什么?

1. 引入了商店的子类将商店和比萨解耦;

2. 引入了新类型的工厂将比萨和原料解耦。

14. 定义抽象工厂模式

提供一个接口,用于创建相关或依赖对象的的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组有关的产品,而不需要知道(关心)实际产出的具体产品是什么。这样依赖,客户就与具体的产品中被解耦,让我们看看类图。

简单工厂模式,工厂方法模式和抽象工厂模式。

注意到了吗,其实抽象工厂的方法都是工厂方法。

总结:

1. 所有的工厂都是用来封装对象的创建;

2. 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦;

3. 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象;

4. 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中;

5. 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合;

6. 工厂方法允许类将实例化延迟到子类进行;

7. 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类;

8. 依赖倒置原则:知道我们避免依赖具体类型,而要尽量依赖抽象;

9. 工厂是很有威力的技巧,帮助我们针对抽象编程,而不针对具体类编程。

简单工程模式、工厂方法模式以及抽象工厂模式的区别见:https://m.php.cn/java/guide/435553.html

相关文章: