导读:前文设计模式(四)简单工厂模式介绍了简单工厂模式,本篇开始介绍工厂方法模式,继续优化简单工厂模式,更好的满足开闭原则和可扩展性。
工厂方法模式解决的问题
简单工厂模式存在如下的缺点,而工厂方法模式能够解决这些问题:
- 在简单工厂中,所有的产品子类的实例创建都是在一个静态工厂方法中创建,如果工厂方法出现问题,就会导致所有引用工厂的客户端出现问题;
- 如果产品下增加新的产品,简单工厂必须进行修改支持新的产品,违背了开闭原则;
- 简单工厂中把所有的产品创建都集中在一个方法中,违背了单一职责原则;
- 简单工厂使用静态方法,造成无法通过继承来扩展工厂方法;
工厂方法模式定义
工厂方法模式定义了一个创建对象的接口,但由子类或实现接口的类决定要创建或实例化的类是哪一个。工厂方法让类的实例化推迟到子类中。简单来说,工厂方法模式会创建出很多具体的工厂方法子类,其共同继承一个工厂父类或工厂接口。
工厂方法模式的UML类图
工厂方法模式的UML类图工厂方法模式角色划分
- 抽象产品(或者产品接口),如上图中Factory
- 具体产品,如上图中的ConcreteProduct1
- 抽象工厂(或者工厂接口),如Factory
- 具体工厂,如ConcreteFactory1
工厂方法模式的示例代码
抽象产品
这里以Car代表抽象产品,相当于UML类图中的Product角色,代码如下:
public class Car {
private String name;
public Car() {
this.name = "This is a Car";
}
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void drive() {
System.out.println("driving on road");
}
}
具体产品
具体产品BenzCar、BMWCar、LandRoverCar,相当于UML类图中的ConcreteProduct角色,代码如下:
public class BenzCar extends Car {
public BenzCar() {
super("BenzCar");
}
public String getName() {
return super.getName();
}
public void drive() {
System.out.println(getName() + " driving on road");
}
}
public class BMWCar extends Car {
public BMWCar() {
super("BMWCar");
}
public String getName() {
return super.getName();
}
public void drive() {
System.out.println(getName() + " driving on road");
}
}
public class LandRoverCar extends Car {
public LandRoverCar() {
super("LandRoverCar");
}
public String getName() {
return super.getName();
}
public void drive() {
System.out.println(getName() + " driving on road");
}
}
抽象工厂
这里以Factory来代表抽象工厂
public interface Factory {
/**
* 抽象工厂方法,子类实现
* @return
*/
Car getCar();
}
具体工厂
这里有三个具体工厂BenzCarFactory、BMWCarFactory、LandRoverCarFactory
public class BenzCarFactory implements Factory {
@Override
public Car getCar() {
return new BenzCar();
}
}
public class BMWCarFactory implements Factory {
@Override
public Car getCar() {
return new BMWCar();
}
}
public class LandRoverCarFactory implements Factory {
@Override
public Car getCar() {
return new LandRoverCar();
}
}
客户端测试类
分别创建了三个具体工厂,用来创建三种不同的汽车产品
public class Client {
public static void main(String[] args) {
Factory factory = new BenzCarFactory();
Car car = factory.getCar();
car.drive();
factory = new BMWCarFactory();
car = factory.getCar();
car.drive();
factory = new LandRoverCarFactory();
car = factory.getCar();
car.drive();
}
}
输出结果:
BenzCar driving on road
BMWCar driving on road
LandRoverCar driving on road
工厂方法模式的优点
- 每个具体工厂只负责创建一种具体产品,职责单一,满足单一职责原则。
- 这一类产品中新增产品时,原有的抽象工厂和具体工厂都不用修改,只需要新增一个具体的工厂类即可,满足了开闭原则。
工厂方法模式的缺点
- 新增产品时,不仅需要需要增加产品类,还需要增加与之对应的具体工厂类,当产品的数量众多时,类的数量将爆发式增长,复杂度变高。
- 工厂方法只能对同一类的产品进行创建,当需要增加其他类别的产品,比如动物类时,仍需要修改抽象工厂方法类,在里面增加创建动物类的方法,因此开闭原则只是局部满足,并非完美满足。
该是总结经验的时候了
在本篇文章,我们学习了更加可扩展的工厂方法模式。我们已经学习到,创建多个对象时可以抽离变化的部分,将代码封装起来。
那么工厂模式到底能带来哪些好处呢。有许多好多,将创建对象的代码封装起来,可以达到代码的复用,避免重复的代码,利于维护。同时,我们也知道创建对象要尽量依赖接口,而不是具体类。依赖接口而不针对实现编程,可以增加我们代码的弹性,扩展性更好。
网友评论