工厂方法模式是我们前面提到的简单工厂模式的延伸,他是GoF23中的创建型模式,解决的仍然是产品对象创建相关问题,也是我们比较常用的一种设计模式。
1.基本定义
工厂方式法模式(Factory Method),定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。类型是创建型模式。
1.1优点
- 用户只需关心产品创建所需的工厂,不必关心产品创建的细节。
- 加入新产品符合开闭原则,提高可扩展性。
1.2缺点
- 类的个数容易过多,增加系统的负责度。
- 增加了系统的抽象性和理解难度。
2.coding
我们仍然以车辆生产作为背景介绍工厂方法模式,虚拟的情况不用对号入座。供应商有若干个工厂,可以生产各种汽车,比如奔驰、别克、法拉利等等。根据订单情况,选择生产。代码如下:
2.1 v0.1版
创建产品类(接口或者抽象类)
package com.xxfamly.creational.factoryMethod;
/**
* 产品:汽车
*/
public interface Car {
//启动
public void power();
}
创建工厂类(接口或者抽象类)
package com.xxfamly.creational.factoryMethod;
/**
* 工厂
*/
public interface Factory {
/**
* 生产汽车
* @return
*/
public Car createCar();
}
假如说目前订单需要生产奔驰汽车,那么我们创建具体的产品类和工厂类。
奔驰汽车类
package com.xxfamly.creational.factoryMethod;
/**
* 具体产品类:奔驰汽车
*/
public class BenzCar implements Car {
@Override
public void power() {
System.out.println("本田发动了");
}
}
奔驰工厂类,敲黑板:子类决定实例化哪一个类。
package com.xxfamly.creational.factoryMethod;
/**
* 具体工厂类:奔驰工厂
*/
public class BenzFactory implements Factory {
/**
* 生产奔驰汽车
* @return
*/
@Override
public Car createCar() {
return new BenzCar();
}
}
客户端类
package com.xxfamly.creational.factoryMethod;
/**
* 模拟客户端类
*/
public class Client {
public static void main(String[] args){
//生产奔驰汽车,并测试发动
Factory benzFactory = new BenzFactory();
Car benz = benzFactory.createCar();
benz.power();
}
}
运行结果
奔驰生产了
奔驰发动了
Process finished with exit code 0
查看UML类图
只生产了1种车型,无论从类图还是代码上,都看不出工厂模式有什么优势,我们接着往下看。
2.2 v0.2版
现在需求有扩展,需要生产别克车型并发动测试。这时候工厂模式的优势就发挥出来了,我们只需要增加具体的产品类和工厂类即可,对原有程序没有任何冲击(客户端除外)。
增加别克产品类
package com.xxfamly.creational.factoryMethod;
/**
* 具体产品类:别克汽车
*/
public class BuickCar implements Car {
@Override
public void power() {
System.out.println("别克发动了");
}
}
增加别克工厂类
package com.xxfamly.creational.factoryMethod;
/**
* 具体工厂类:别克工厂
*/
public class BuickFactory implements Factory {
/**
* 生产别克汽车
* @return
*/
@Override
public Car createCar() {
System.out.println("别克生产了");
return new BuickCar();
}
}
修改客户端
package com.xxfamly.creational.factoryMethod;
/**
* 模拟客户端类
*/
public class Client {
public static void main(String[] args){
//生产奔驰汽车,并测试发动
Factory benzFactory = new BenzFactory();
Car benz = benzFactory.createCar();
benz.power();
//生产别克汽车,并测试发动
Factory buickFactory = new BuickFactory();
Car buick = buickFactory.createCar();
buick.power();
}
}
运行结果
奔驰生产了
奔驰发动了
别克生产了
别克发动了
Process finished with exit code 0
查看UML类图
从类图和实际Coding都可以看出我们前面所说的工厂方法模式的优点,理论上看可以横行扩展很多产品类和工厂类来完成需求的不断变化。