Java设计模式-工厂方法模式
1. 定义
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工具方法使一个类的实例化延迟到其子类。
工厂方法模式通用类图
2. 实例
在我们日常生活中,很多的工厂会用来生产产品,并进行组装。我们这里有一个生产机床(Creator)生产三种不同的产品(ProductA、ProductB、ProductC)。车间工人在生产的时候只需要根据使用情况,输入需要生产的产品类型(ABC类)就可以获取到我们需要的产品了。
抽象机床类
/**
* 抽象机床类
*/
public abstract class AbstraceCreator {
/**
* 生产产品
* @param c 产品类
* @param <T> 泛型
* @return 根据传入的产品类创建一个实例
*/
public abstract <T extends Product> T create(Class<T> c);
}
机床类实现
public class Creator extends AbstraceCreator {
@Override
public <T extends Product> T create(Class<T> c) {
Product product = null;
try {
//根据传入的类型创建一个产品
product = (T) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
产品类
/**
* 产品接口
*/
public interface Product {
//下线组装方法
void assemble();
}
/**
* 产品A
*/
public class ProductA implements Product{
@Override
public void assemble() {
System.out.println("A产品上线组装");
}
}
/**
* 产品B
*/
public class ProductB implements Product{
@Override
public void assemble() {
System.out.println("B产品上线组装");
}
}
/**
* 产品C
*/
public class ProductC implements Product {
@Override
public void assemble() {
System.out.println("C产品上线组装");
}
}
生产过程模拟
public class Main {
public static void main(String[] args) {
AbstraceCreator creator = new Creator();
Product productA = creator.create(ProductA.class);
Product productB = creator.create(ProductB.class);
Product productC = creator.create(ProductC.class);
productA.assemble();
productB.assemble();
productC.assemble();
}
}
输出结果
A产品上线组装
B产品上线组装
C产品上线组装
Process finished with exit code 0
3. 应用
3.1 优点
- 具有良好的封装性,代码结构清晰。
- 工厂方法模式的拓展性优秀。
- 可以屏蔽产品类。调用者不必关心产品类的具体实现,只需要关心产品类的接口保持不变,系统的上层架构就不会发生改变。
- 工厂方法是典型的解耦框架。
3.2 使用场景
- 替代new方法创建对象
- 需要灵活可拓展的框架时,可以考虑工厂方法模式。
- 使用在异构项目中。
- 使用在测试驱动开发的框架下。
4. 拓展
4.1 简单工厂模式
如果一个模块只需要一个工厂类,那么不必让一个工厂类去继承一个抽象类或实现一个接口,只需要使用一个静态方法就可以实现同样的功能。
我们参照上面的实例,制作一个新的类图,来模拟一下简单工厂模式的实现。
4.2 多个工厂模式
多个工厂模式就是遇到初始化一个对象十分耗费精力(创建流程比较复杂或耗费更多的时间和资源)时,这样把所有的产品类都放在同一个工厂方法中进行实例化就会是代码结构不清晰。这时候我们可以使用多个工厂类,每一个工厂类只负责实例化其中一种产品。
我们再一次修改类图,得到多个工厂模式的类图。
4.3 替代单例
我们上一篇博客中介绍了单例的实现方式,一个单例的通用类图为:
在使用工厂方法模式时,我们也可以通过反射的机制来创建单例
/**
* 工厂模式实现单例
*/
public class SingletonFactory{
private static Singleton singleton;
static {
try{
Class clazz = Class.forName(Singletong.class.getName());
//获取无参构造函数
Constructor constructor = clazz.getDeclaredConstructor();
//设置无参构造可以访问
constructor.setAccessible(true);
//通过放射创建一个实例
singleton = (Singleton) constructor.newInstance();
} catch (Exception e){
e.printStackTrace();
}
}
public static Singleton getInstance(){
return singleton;
}
}