「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」。
1.模式定义
工厂方法模式简称工厂模式,也可以叫虚拟构造器模式或者多态工厂模式,在这个模式中工厂父类负责定义创建产品对象的公共接口,工厂的子类负责创建具体产品类的实例也就是具体的产品对象,这样做的目的就是通过工厂子类来确定具体要创建哪个产品的实例
2.模式结构
工厂方法模式包含四个角色:
- Factory:抽象工厂角色
- ConcreteFactory:具体工厂角色
- Product:抽象产品角色
- ConcreteProduct:具体产品角色
3.时序图
4.代码分析
代码案例:以简单工厂模式中的例子为例,假设我现在有一条电脑工厂,有笔记本电脑生产线和台式电脑生产线,随着社会发展需要增加手机的生产线,显然无法在电脑工厂中加入手机的生产线,因此我就需要把工厂升级为超级工厂,既可以生产电脑又可以生产手机,同时以后还可以生产其他的产品。
代码中有四个角色:
- Factory:抽象工厂角色
- Product:抽象产品角色
- DesktopComputer:台式电脑生产线
- XiaoMiPhone:小米手机生产线
/**
* 抽像工厂类
*/
public abstract static class Factory {
public abstract Product buildFactory();
}
/**
* 具体工厂类——电脑生产线
*/
public static class ComputerFactory extends Factory {
@Override
public Product buildFactory() {
return new DesktopComputer();
}
}
/**
* 具体工厂类——手机生产线
*/
public static class PhoneFactory extends Factory {
@Override
public Product buildFactory() {
return new XiaoMiPhone();
}
}
/**
* 抽象产品类
*/
public abstract static class Product {
public abstract void buildProduct();
}
/**
* 具体产品类——台式电脑生产线
*/
public static class DesktopComputer extends Product {
@Override
public void buildProduct() {
System.out.println("我生产了台式电脑");
}
}
/**
* 具体产品类——小米手机生产线
*/
public static class XiaoMiPhone extends Product {
@Override
public void buildProduct() {
System.out.println("我生产了小米手机");
}
}
public static void main(String[] args) {
//实例化电脑生产线
Factory computerFactory = new ComputerFactory();
computerFactory.buildFactory().buildProduct();
//实例化手机生产线
Factory phoneFactory = new PhoneFactory();
phoneFactory.buildFactory().buildProduct();
}
运行结果:
我生产了台式电脑
我生产了小米手机
5.模式分析
工厂方法模式是简单工厂模式的进一步扩展,将在简单工厂模式中的核心工厂类负责创建具体产品类的实例的工作交给了工厂方法模式中的具体工厂模式,这样核心工厂模式就只专注于具体工厂类的方法提供,这样弥补了简单工厂模式的缺点。
6.优点
- 工厂方法模式中客户只需要知道自己需要的产品由哪一个具体工厂生产的即可,不用知道这个产品是由哪一个具体的产品类生产的,也不用关心具体的产品类是什么时候被实例化的,甚至不用知道具体产品类的类名;
- 工厂方法模式的核心是工厂角色和产品角色,他们都是基于多态性设计的,它能够使工厂自主确定创建何种产品对象生,而如何创建这个对象的细节则完全封装在工厂内部。而又因为所有的具体工厂都具有同一个父类,因此工厂方法模式又被称为多态工厂模式;
- 与简单工厂模式相比,工厂方法模式最大的变化在于如果新增加一个产品,是不用修改核心工厂类的,只需要创建一个具体的工厂类和一个具体的产品类就可以了。
7.缺点
- 每增加一个产品时就需要增加一个具体的产品类和具体的工厂类,长此以往系统就会越发臃肿,在编译和运行时会给系统带来额外的开销;
- 因为该模式具有良好的可扩展性,所以就需要引入抽象类,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。
8.适用环境
- 一个类不需要知道它所需要对象的类:客户端不需要知道具体产品的类,只需要知道产品由哪个工厂创建的;
- 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
9.扩展
- 使用多个工厂方法:工厂模式有一个抽象的父类,这个父类中可以定义更多的方法,这样具体的工厂类中就可以在这些方法中实现不同的逻辑,来满足不同的业务需求;
- 产品对象的重复使用:工厂对象可以将已经创建过的产品对象保存在一个集合中(数组、List等),这样当下一次遇到需要创建这个产品时可以直接从数组中查找,如果在数组中没有查询到需要的产品对象就去创建这个对象,然后将这个对象添加到集合中再返回给客户端
- 多态性的丧失和模式的退化:工厂模式利用的是多态的特点,如果只有一个具体的工厂类那么多态的意义就没有了,此时工厂方法模式就有些大材小用了,因此这时可以退一步使用简单工厂模式。
参考链接:工厂方法模式