Define an interface for creating an object, but let subclasses decide which class to insantiate.Factory Method lets a class defer instantiation to subclasses.
本篇博客属于《Java设计模式》系列之一,内容主要借鉴于 秦小波的著作《设计模式之禅》,在理解过程中可能还参考其他博主的知识,最后整理成自己的学习笔记,在此分享给大家。由于本人知识和能力有限,博客中有错误或者理解偏差的地方,还望大佬们多多指点,感谢不尽。(目前处于实习阶段,设计模式配合个人的实际经验更下饭,暂时更新最常见设计模式9+1篇。立个flag,将来一定会补齐)–2020.11.22
定义
定义一个用于创建对象的接口,然子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂方法的通用类图:
工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。
抽象产品类代码清单:
public abstract class Product {
// 产品的公共方法
public void method1(){
// 业务逻辑
}
// 抽象方法
public abstract void method2();
}
具体的产品类可以分为多个,都继承自抽象产品类:
public class ConcreteProduct1 extends Product {
@Override
public void method2() {
// 业务逻辑处理
}
}
public class ConcreteProduct2 extends Product{
@Override
public void method2() {
// 业务逻辑
}
}
抽象工厂类负责定义产品对象的产生:
public abstract class Creator {
/**
* 创建一个产品对象,其输入参数类型可以自行设置
* 通肠胃String Enum Class等
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
具体工厂类:
public class ConcreteCreator extends Creator{
@Override
public <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try{
product = (Product)Class.forName(c.getName()).newInstance();
}catch (Exception e){
// 异常处理
}
return (T)product;
}
}
场景类调用:
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
/**
* 继续处理业务
*/
}
}
优点
- 有良好的封装性,代码结构清晰:创建产品对象,不需要知道创建过程,只要知道类名就可以,降低模块间的耦合。
- 工厂方法模式的扩展性非常优秀:想要增加产品类,只要适当修改具体的工厂类或者扩展一个工厂类,就可以“拥抱变化”。
- 屏蔽产品类。不关心产品类的实现,只需要关心接口。如:使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的只是切换一下驱动名称(前提是SQL是标准语句)。
工厂模式是典型的解耦框架,其他实现类不需要关心,符合迪米特法则;符合依赖倒置原则,只依赖产品类的抽象;符合里式替换原则,产品子类替换产品父类,没问题!
简单工厂与多个工厂
当一个模块只需压一个工厂类的时候,没有必要把它生产出来,直接使用静态方法。这样称为简单工厂模式,也称作静态工厂模式。实现比较简单,逻辑更为简化,缺点是工厂类的扩展比较困难,不符合开闭原则。
举个栗子:女娲造人,女娲可以造三种人:黑色、白色、黄色人种。她一个个捏,就太慢了,于是使用工厂模式。工厂模式类图:
在简单工厂模式中:
在一个复杂项目的里面,如果把所有的产品类都放在一个工厂方法中进行初始化会使代码结构不清晰。例如一个产品有五个具体实现,每个实现类的初始化方法都不相同,如果都写在一个方法中,会导致该方法臃肿。
可以为每一个产品定义一个创造者,然后由调用者自己去选择与那种工厂方法关联。这样创建类的职责清晰,结构简单。但是扩展时就需要建立一个相应的工厂类。
在多工厂的时候,增加一个协调类,避免调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层次模块提供统一的访问接口。
在框架中的使用
- Mybatis中的DataSourceFactory、SqlSessionFactory、ObjectFactory