1.介绍
1.1 定义
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
1.2 作用
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化哪一个类。
2.模式原理
2.1 工厂方法模式通用类图
2.2 模式角色组成关系表
角色 | 关系 | 作用 |
---|---|---|
抽象产品(Product) | 具体产品的父类 | 具体产品类的公共接口 |
具体产品(ConcreteProduct) | 抽象产品的子类,工厂类创建的目标类 | 生产的具体产品 |
抽象工厂(Creator) | 具体工厂的父类 | 具体工厂的公共接口 |
具体工厂(ConcreteCreator) | 抽象工厂的子类 | 创建产品类的具体工厂 |
3.代码示例
示例业务背景:有一家工厂在为客户生产白色汽车和黄色汽车,并且客户随时有可能需要生产更多颜色的汽车,我们以工厂方法模式来实现这一需求。
3.1 实现步骤
1.创建抽象产品类,定义具体产品类的公共接口
public abstract class Car {
/**
* 汽车颜色
*/
public abstract void getColor();
}
2.创建具体产品类,继承抽象产品类,定义生产的具体产品
public class WhiteCar extends Car {
@Override
public void getColor() {
System.out.println("白色汽车");
}
}
public class YellowCar extends Car {
@Override
public void getColor() {
System.out.println("黄色汽车");
}
}
3.创建抽象工厂类,定义具体工厂的公共接口
public abstract class CarFactory {
/**
* 生产汽车工厂方法
* @return
*/
public abstract <T extends Car> T createCar(Class<T> c);
}
4.创建具体工厂类,继承抽象工厂类,定义创建对应具体产品的方法
/**
* @author :
* @create :Created in 2020-11-25
* @description:具体工厂类
**/
public class CarConcreteFactory extends CarFactory {
@Override
public <T extends Car> T createCar(Class<T> c) {
try {
Car car = (Car) Class.forName(c.getName()).newInstance();
return (T)car;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
5.场景类,调用具体工厂类的方法,创建不同颜色的汽车
/**
* @author :
* @create :Created in 2020-11-25
* @description:场景类
**/
public class client {
public static void main(String[] args){
CarConcreteFactory carConcreteFactory = new CarConcreteFactory();
//生产白色汽车
WhiteCar whiteCar = carConcreteFactory.createCar(WhiteCar.class);
whiteCar.getColor();
//生产黄色汽车
YellowCar yellowCar = carConcreteFactory.createCar(YellowCar.class);
yellowCar.getColor();
}
}
执行结果如下:
白色汽车
黄色汽车
4.优缺点
4.1 优点
良好的封装性,代码结构清晰。需要创建什么产品,只需要知道这个产品的类名(或者约束字符串),调用具体的产品工厂类创建就可以了,不需要知道创建的过程,降低了模块之间的耦合。以及工厂方法模式拥有良好的扩展性,如实例代码中,如果需要新增一种黑色的汽车,不需要修改已有的代码,只需要新增一个继承抽象产品类的具体产品类即可。
工厂方法模式是典型的解耦框架,高层模块只需要知道产品的抽象类,其它的实现类都不用关心,符合迪米特法则(最少知道原则),良好的扩展性,和符合开闭原则。
4.2 缺点
当有大量的产品类时,增加了代码量,在一定程度上增加了系统的复杂度。
5.使用场景
工厂方法模式是new一个对象的替代品,所以在需要实例化对象的地方都可以使用。在面对需要灵活的、可扩展的业务时,可以考虑使用工厂方法模式。