工厂方法模式
定义
工厂方法模式就是定义创建产品对象的工厂接口,将产品对象的实际创建工作延迟到具体子类中执行。满足创建型模式的“创建与使用相分离”的原则。
优缺点
优点:
用户只要知道具体工厂的名称就能得到产品,无需知道产品的具体创建过程。
灵活性增强,对于新产品的创建就只需要多写一个相应工厂类。
典型的解耦框架。高层只需要知道产品的抽象类,无需关心其它实现类,满足迪米特原则,依赖倒置原则,里氏替换原则。
缺点:
类的个数容易增多,增加复杂度。
增加了系统的抽象性和理解程度。
一种具体工厂只能生产一种产品。
类图
抽象工厂:Creator抽象类提供createProject()来创建产品。
具体工厂:ConcreteCreator实现抽象工厂的方法,完成产品创建。
抽象产品:Phone抽象类提供一个拍照的方法,定义手机的拍照功能。
具体产品:小米手机和一加手机继承了手机抽象类的拍照特性。
代码如下
/**
* @description: 抽象工厂
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
abstract class Creator{
/**
* 生产产品
* @author: Suy
* @date: 2021/4/11
* @param c
* @return T
**/
public abstract<T extends Phone> T createProduct(Class<T> c);
}
/**
* @description: 具体工厂
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
class ConcreteCreator extends Creator{
@Override
public <T extends Phone> T createProduct(Class<T> c) {
Phone phone = null;
try {
//这里通过反射来获取对象
phone = (Phone)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("创建失败");
}
return (T)phone;
}
}
/**
* @description: 抽象手机类
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
abstract class Phone{
/**
* 拍照
* @author: Suy
* @date: 2021/4/11
* @param null
* @return null
**/
public abstract void takePictures();
}
/**
* @description: 小米手机
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
class MiPhone extends Phone{
@Override
public void takePictures() {
System.out.println("使用小米手机拍照... 看清世界,让记忆充满细节");
}
}
/**
* @description: 小米手机
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
class OnePlusPhone extends Phone{
@Override
public void takePictures() {
System.out.println("使用一加手机拍照...总有故事,被影像看见");
}
}
/**
* @description: 工厂方法模式
* @author: Suy
* @createDate: 2021/4/11 15:13
*/
public class FactoryMethod {
public static void main(String[] args) {
Creator c = new ConcreteCreator();
MiPhone miPhone = c.createProduct(MiPhone.class);
miPhone.takePictures();
OnePlusPhone onePlusPhone = c.createProduct(OnePlusPhone.class);
onePlusPhone.takePictures();
}
}
扩展
工厂方法模式是new对象的替代品,在所有需要生成对象的地方都可以使用,但是需要慎重加入一个工厂类进行管理,会增加代码的复杂度。
需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。例如需要设计一个使用Hibernate来连接数据库时,有两种数据库可供选择:MySql和Oracle,我们可以增加一个加载驱动的接口,实现方法就根据不同的数据库来加载不同的驱动以及其他配置,按照传入不同的标识来进行切换。
最后,可以使用在测试驱动开发的框架下。例如,测试一个类A,就需要把与类A有关联关系的类B也同时产生出来,我们可以使用工厂方法模式把类B虚拟出来,避免类A与类B的耦合。目前由于JMock和EasyMock的诞生,该使用场景已经弱化了,读者可以在遇到此种情况时直接考虑使用JMock或EasyMock。
想获取到更多设计模式内容请关注”爱笑的草帽“的公众号。