工厂方法模式是对简单工厂模式的进一步抽象化和推广,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
一、工厂方法模式
1、工厂方法模式的定义
工厂方法模式(Factory Method Pattern),又叫作多态性工厂模式。
指定义一个创建对象的接口,让子类决定实例化哪一个类,工厂方法把一个类的实例化推迟到其子类中进行。
工厂方法模式解决了简单工厂生产太多产品导致其内容代码臃肿(if条件太多)的问题,也符合开闭原则。
2、工厂方法模式的结构
(1)模式的结构
工厂方法模式的主要角色如下:
- 抽象工厂(Abstract Factory)
是工厂方法模式的核心,与应用程序无关。提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。 - 具体工厂(ConcreteFactory)
实现抽象工厂接口的具体工厂类,重写创建对象方法来完成具体产品的创建。 - 抽象产品(Product)
是所有对象的超类,定义了产品的规范,描述了产品的共同主要特性和功能。 - 具体产品(ConcreteProduct)
实现了抽象产品角色所定义的接口,某个产品对象由专门的具体工厂来创建,具体产品和具体工厂之间往往一一对应。
(2)结构图如下:(图来自网络)
3、优缺点
主要优点:
- 用户只需要知道具体工厂的名称就可得到想要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
- 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
主要缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
4、使用场景
- 客户端不关心创建产品的细节,只关心创建产品的工厂名。创建产品对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 一个类通过其子类来指定创建哪个产品对象。
5、在框架源码中使用也很广泛
- Logback源码中 ILoggerFactory
二、模式的通用实现
代码如下:
public class FactoryMethodPattern {
public static void main(String[] args) {
try {
AbstractFactory factory1 = new ConcreteFactory1();
Product product1 = factory1.newProduct();
product1.show();
AbstractFactory factory2 = new ConcreteFactory2();
Product product2 = factory2.newProduct();
product2.show();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
//抽象产品:提供了产品的接口
interface Product {
public void show();
}
//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product {
@Override
public void show() {
System.out.println("具体产品1显示...");
}
}
//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product {
@Override
public void show() {
System.out.println("具体产品2显示...");
}
}
//抽象工厂:提供了厂品的生成方法
interface AbstractFactory {
public Product newProduct();
}
//具体工厂1:实现了厂品的生成方法
class ConcreteFactory1 implements AbstractFactory {
@Override
public Product newProduct() {
System.out.println("具体工厂1生成-->具体产品1...");
return new ConcreteProduct1();
}
}
//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory {
@Override
public Product newProduct() {
System.out.println("具体工厂2生成-->具体产品2...");
return new ConcreteProduct2();
}
}
三、模式的应用实例
简易计算器为例,需求:输入两个数和运算符,得到结果。传送门:简单工厂模式
简单工厂模式的实现改造成工厂方法模式实现。
1、抽象工厂
public interface IOperationFactory {
IOperation createOperation();
}
2、具体工厂
- 加法
public class AddFactory implements IOperationFactory{
@Override
public IOperation createOperation() {
return new OperationAdd();
}
}
- 除法,其他同理
public class DivFactory implements IOperationFactory {
@Override
public IOperation createOperation() {
return new OperationDiv();
}
}
3、抽象产品
public interface IOperation {
double compute (double number1, double number2) throws Exception;
}
4、具体产品
- 加法
public class OperationAdd implements IOperation {
@Override
public double compute(double number1, double number2) {
return number1 + number2;
}
}
- 除法,其他同理
public class OperationDiv implements IOperation {
@Override
public double compute(double number1, double number2) throws Exception {
if(number2 == 0){
throw new Exception("除数不能为0!");
}
return number1 / number2;
}
}
5、测试
public static void main(String[] args) throws Exception {
double num1 = 10;
double num2 = 2;
IOperationFactory addFactory = new AddFactory();
IOperation add = addFactory.createOperation();
System.out.println(add.compute(num1, num2));
IOperationFactory divFactory = new DivFactory();
IOperation div = divFactory.createOperation();
System.out.println(div.compute(num1, num2));
}
参考文章:
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。