一、简介
- 概念:定义了一个创建对象的抽象方法,由子类决定要实例化的类,将对象实例化推迟到子类进行。
按照前面讲解的简单工厂模式,假如随着需求不断变化,系统需要优化,想将宝马汽车、奔驰汽车等不同品牌的汽车分开生产,可能后面会扩展不同品牌不同厂家这种情况。针对这种情况,我们可以使用工厂方法模式创建不同品牌汽车的工厂,这样的话,他们之间互不影响。后面如果想扩展其他品牌的话,也无需改动旧代码,直接添加多一个工厂实现类即可。
二、工厂方法模式
相关类图如下:
通过类图可以看到,工厂方法模式有四个要素:
- 抽象工厂类:抽象工厂类是工厂方法模式的核心,与调用者直接交互用来提*品,可以是接口,也可以是抽象类。
- 具体工厂实现:工厂实现是具体的实例化对象的类,如果需要扩展新的产品种类,就增加多一个工厂的实现即可。
- 产品接口:产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
- 产品实现:实现产品接口的具体类,决定了产品在客户端中的具体行为。
具体代码实现如下:
【a】ICar汽车接口
/**
* @Description: ICar汽车接口
* @author: weixiaohuai
* @Date: 2019/10/19 20:49
*/
public interface ICar {
/**
* 生产汽车
*/
void productCar();
}
【b】BmwCar宝马汽车类
/**
* @Description: BmwCar宝马汽车类
* @author: weixiaohuai
* @Date: 2019/10/19 20:49
*/
public class BmwCar implements ICar {
@Override
public void productCar() {
System.out.println("生产宝马汽车...");
}
}
【c】BenzCar奔驰汽车类
/**
* @Description: BenzCar奔驰汽车类
* @author: weixiaohuai
* @Date: 2019/10/19 20:49
*/
public class BenzCar implements ICar {
@Override
public void productCar() {
System.out.println("生产奔驰汽车...");
}
}
【d】抽象工厂抽象接口
/**
* @Description: 工厂抽象接口
* @author: weixiaohuai
* @Date: 2019/10/19 20:49
*/
public abstract class ICarFactory {
/**
* 创建产品方法
*
* @return ICar
*/
abstract ICar createCar();
}
【e】宝马汽车工厂具体实现类
public class BmwCarFactory extends ICarFactory {
@Override
ICar createCar() {
return new BmwCar();
}
}
【f】奔驰汽车工厂具体实现类
public class BenzCarFactory extends ICarFactory {
@Override
ICar createCar() {
return new BenzCar();
}
}
【g】客户端
public class Client {
public static void main(String[] args) {
ICarFactory bmwCarFactory = new BmwCarFactory();
bmwCarFactory.createCar().productCar();
ICarFactory benzCarFactory = new BenzCarFactory();
benzCarFactory.createCar().productCar();
}
}
【h】运行结果
可见,各种类的汽车产品之间生产互不影响,耦合度降低。假如后期还想生产别的种类的汽车,那么只需要增加多一个对应的工厂实现即可,可见扩展性还是维护性都比简单工厂提高了不少。
三、总结
- 优点:
- 使用工厂方法模式之后,让工厂实现去决定到底实例化哪一种产品,将产品实例化放在子类来进行。这样的话,客户端调用的时候无须关心产品如何实现的,直接调用方法即可,耦合度大大降低。并且如果以后想扩展别的产品工厂,只需增加一个工厂实现即可进行扩展,扩展性大大提高。
- 缺点:
- 如果产品的生产过程并不复杂,假如直接通过new Object()就能实例化对象的,那么就无须使用工厂方法,反而让系统多了一些工厂方法接口和实现,不方便管理,可维护性差。