一、概述
工厂方法模式针对不同的产品提供不同的工厂,其定义为:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类,该模式又称为工厂模式,虚拟构造器模式或多台工厂模式。它是一种类创建型模式。
结构图为:
二、代码设计
工厂方法模式包含一个抽象产品类Product、具体产品类ConcreteProduct、抽象工厂类Factory以及具体工厂类ConcreteFactory。
抽象工厂类Factory可以是接口,也可以是抽象类或具体类,典型代码如下:
1 | public class interface Factory { |
具体工厂类实现了工厂方法,不同的具体工厂可以创建不同的具体产品,其典型代码如下:
1 | public class ConcreteFactory implements Factory { |
客户端的代码只关心工厂类,不同的具体工厂可以创建不同的产品,客户端典型代码如下:
1 | Factory factory; |
反射
Java反射是指在程序运行时获取已知名称的类或已有对象的相关信息的一种机制,包括类的方法、属性、父类等信息,还包括实例的创建和实例类型的判断等。在反射中使用最多的是Class,Class类的实例表示正在运行的Java应用程序中的类和接口,其forName(String className)方法可以返回与带有给定字符串名的类或接口相关联的Class对象,再通过Class对象的newInstance()方法创建此对象所表示的类的一个新实例,即通过一个类名字符串得到类的实例。
1 | Class c = Class.forName("String"); |
三、demo
设计一个程序读取不同类型的图片格式,GIF图片读取器读取GIF图片,JPG图片读取器读取JPG图片。
抽象产品类Product设计如下:
1 | public interface Image{ |
具体产品类ConcreteProduct类设计如下:
1 | public class GIFImage implements Image { |
1 | public class JPGImage implements Image { |
抽象工厂类Factory设计如下:
1 | public interface ImageFactory { |
具体工厂类ConcreteFactory设计如下:
1 | public class GIFImageFactory implements ImageFactory { |
1 | public class JPGImage implements ImageFactory { |
客户端调用方法如下:
1 | public static void main(String args[]) { |
运行结果如下:
四、总结
1. 优点
- 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
- 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。
- 在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
2. 缺点
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
3. 适用场景
- 客户端不知道它所需要的对象的类。
- 抽象工厂类通过其子类来指定创建哪个对象。