1 模式的定义
工厂方法 (Factory Method) 模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类中。
2 模式的优缺点
工厂模式的主要优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的创建过程。
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,妈祖开闭原则
工厂模式的缺点:
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
3 模式的结构
工厂方法模式的主要角色如下:
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
- 具体工厂:主要实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现了抽象产品角色所定义的接口,有具体工厂创建,它同具体工厂一一对应。
其结构图如图:
4 模式的实现
代码如下
抽象产品:提供了产品的接口
package FactoryMethod;
public interface Product {
public void show();
}
具体产品1:实现抽象产品中的抽象方法
package FactoryMethod;
public class ConcreteProduct1 implements Product{
@Override
public void show() {
System.out.println("具体产品1显示......");
}
}
具体产品2:实现抽象产品中的抽象方法
package FactoryMethod;
public class ConcreteProduct2 implements Product{
@Override
public void show() {
System.out.println("具体产品2显示......");
}
}
抽象工厂:提供产品的生成方法
package FactoryMethod;
public interface AbstractFactory {
public Product newProduct();
}
具体工厂1:实现产品的生成方法
package FactoryMethod;
public class ConcreteFactory1 implements AbstractFactory{
@Override
public Product newProduct() {
System.out.println("具体工厂1生成-->具体产品1......");
return new ConcreteProduct1();
}
}
具体工厂2:实现产品的生成方法
package FactoryMethod;
public class ConcreteFactory2 implements AbstractFactory{
@Override
public Product newProduct() {
System.out.println("具体工厂2生成-->具体产品2......");
return new ConcreteProduct2();
}
}
xml配置文件:工用户设置具体工厂名,以便生成相关产品
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>ConcreteFactory1</className>
</config>
对象生成器:从XML配置文件中提取具体工厂类的类名,并返回一个对象
package FactoryMethod;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.lang.reflect.Constructor;
public class ReadXML {
public static Object getObject() {
try {
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src\\FactoryMethod\\config.xml"));
NodeList nodeList = doc.getElementsByTagName("className");
Node classNode = nodeList.item(0).getFirstChild();
String cName ="FactoryMethod." + classNode.getNodeValue();
Class<?> clazz = Class.forName(cName);
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object obj = constructor.newInstance();
return obj;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
测试类
package FactoryMethod;
public class AbstractFactoryTest {
public static void main(String[] args) {
AbstractFactory af = (AbstractFactory) ReadXML.getObject();
Product product = af.newProduct();
product.show();
}
}
运行结果:
当xml文件中的ConcreteFactory1替换成ConcreteFactory时:
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>ConcreteFactory2</className>
</config>
运行结果为:
5 模式的运用场景
工厂方法模式通常适用于以下场景:
- 客户只知道创建产品的工厂名,而不知道具体的产品名。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌