MENU

Java-43 接口的应用:工厂模式

October 17, 2023 • Read: 64 • Java阅读设置

面向对象编程

工厂模式

1 什么是工厂模式

工厂模式,简单地说,是指在对某些具有某个共同特性的类创建对象时,不直接分别用各个类的构造器创建对应对象,而是专门为这些类的对象的创建设计一个类,称为工厂类,通过调用工厂类对应的创建对象的方法的方式来创建这些不同类的对象。

这样使得对对象的创建和使用都通过调用方式,实现了对象的创建和使用的解耦。

这里特别强调了这些类有共同的特性,是模拟出工厂模式的作用场景:要使用不同类的这个共同特性的对应功能。

不考虑工厂模式时,要先分别创建对应类的对象,再通过对象去调用对应方法。
有工厂模式时,先调用工厂类的创建对象的方法,再调用对应功能的方法,使得整个过程没有new的创建对象的代码,通过调用的方式实现创建和使用。

无工厂模式示例:
2023-10-17T04:11:16.png

工厂模式分为3种类型:简单工厂模式、工厂方法模式和抽象工厂模式。

2 简单工厂模式

简单工厂模式是指对这些具有共同特性的类定义一个工厂类专门为它们创建对象,该工厂类中定义一个静态方法来实现专门为它们创建对象。

由于这些类由它们的共同特性即接口联系在一起,因此工厂类中的用于实现创建对象的静态方法返回的类型为该接口对应的类型,代表着该方法返回创建的该接口类型的对象。

由于对不同类的对象的创建实际上要通过使用对应的构造器实现,因此必须在创建对象的静态方法中设置一个参数来接收要创建对象的类是哪个类,通常该参数设置为字符串类型,根绝参数返回对应构造器创建的对应对象。

这样在创建这些类的对象时,都通过调用该工厂类的静态方法,传入对应类对应的参数来实现。

简单工厂模式示例:
2023-10-17T04:15:41.png

3 工厂方法模式

工厂方法模式是简单工厂模式的改进:
在简单工厂模式中,要扩展新类的对象的创建,必须对工厂类中现有的静态方法进行修改。
扩展时更好的方式是不对已有的代码修改,而是直接在现有代码的基础上加上新代码,这样保证了即使加的新代码出现了问题,也不影响已有代码,只需修改新代码。
工厂方法模式就是遵循了这样的方法。

工厂方法模式是指为要创建的这些类定义一个抽象类或接口作为创建它们对象的抽象工厂“类”,其中定义抽象方法来实现对不同类的对象的创建,因此该抽象方法的返回值为这些类对应接口(共同特性)对应的类型。
再对各个类分别创建对应的继承或实现该抽象工厂“类”的具体工厂类,在对应具体工厂类中重写创建对象的抽象方法实现本类对象的创建。

这样在创建这些类的对象时,流程上都是通过调用抽象工厂“类”对应的抽象方法来实现,在实现上必须通过实例化对应的继承或实现该抽象工厂“类”的具体工厂类的对象来调用对应重写的创建对应对象的抽象方法。

这样如果扩展新类,也只需在现有代码基础上,添加新类对应于抽象工厂“类”的继承子类或实现类代码即可。

工厂方法模式示例:
2023-10-17T04:24:10.png

4 抽象工厂模式

前面的工厂模式都是针对具有某个共同特性的一些类,简单地说,针对一种类。
抽象工厂模式是针对多种类,每种类是一群具有某个共同特性的不同类。

在抽象工厂模式中,仍是先定义一个能创建所有这些类的对象的抽象工厂“类”,即可以是抽象类也可以是接口,其中定义实现创建这些类的对象的抽象方法,但此时不再是一个抽象方法,而是有几种类就要定义几个对应的抽象方法,每个抽象方法的返回值就是对应种类的类对应的接口对应的类型。
然后要创建对应的继承或实现抽象工厂“类”的具体工厂类来重写这些抽象方法从而真正实现对应类的对象的创建。
这里不是与工厂方法模式那样分别对每个类创建对应的具体工厂类,而是与简单工厂模式类似,每个种类创建对应的具体工厂类,每个种类的具体工厂类中重写对应抽象方法来实现该种类的类的对象的创建,具体写法与简单工厂模式一致。
由于每个种类的具体工厂类必须要重写所有抽象方法,即包括要重写创建其他种类对象的对应抽象方法,这里往往是只重写本种类的对应的抽象方法,而对于其他种类对应的抽象方法重写时直接返回null,并不真正的去实现。
此外,除了针对每个种类都创建对应的具体工厂类,额外再创建一个能够实现对任何种类的类的对象的创建的具体工厂类,也就是在这个类中真正地重写所有对应种类的对象的创建对应的抽象方法。

这样在创建不同种类时,流程上都是通过调用抽象工厂“类”对应的抽象方法,实现上是先通过对应种类或全种类的具体工厂类的对象,来调用对应重写的抽象方法实现。

抽象工厂模式的示例:
先在前面Shape的基础上,另外定义一种Color类:
2023-10-17T04:35:28.png

抽象工厂“类”:
2023-10-17T04:35:58.png

具体工厂类:
2023-10-17T04:36:20.png

2023-10-17T04:36:34.png

2023-10-17T04:36:48.png

创建和使用测试:
2023-10-17T04:37:08.png