导读:前文设计模式(五)工厂方法模式介绍了工厂方法模式,本篇开始介绍抽象工厂模式,继续优化工厂方法模式,更好的满足开闭原则和可扩展性。
抽象工厂模式解决的问题
在工厂方法模式中,我们已经知道其缺点:只能对同一类的产品进行创建,不能对不同类型的产品簇类型进行创建。
抽象工厂模式可以解决这样的问题。
抽象工厂模式定义
这个模式可以创建产品的家族。提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户端使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品时什么。
抽象工厂模式UML类图
抽象工厂模式角色划分
- 抽象产品(或者产品接口),如上文类图中的AbstractProductA,AbstractProductB;
- 具体产品,如ProductA1,ProductB1;
- 抽象工厂(或者工厂接口),如AbstractFactory;
- 具体工厂,如果ConcreteFactory1,ConcreteFactory2;
- 产品族,如AbstractProductAe产品族中有产品:ProductA1,ProductA2;
抽象工厂使用示例代码
抽象产品家族A:以汽车家族产品为例
首先是家族产品基类Car
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
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");
}
}
汽车子类:BMWCar
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");
}
}
汽车子类:LandRoverCar
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");
}
}
抽象产品家族B:以动物为例
首先是动物基类:Animal,定义了动物的名称和动物行走的行为
public class Animal {
private String name;
private String walkStyle;
public Animal() {
this.name = "Animal";
this.walkStyle = "walk on ground";
}
public Animal(String name, String walkStyle) {
this.name = name;
this.walkStyle = walkStyle;
}
public void walk() {
System.out.println(this.name + " " + this.walkStyle);
}
}
动物子类:Cat
public class Cat extends Animal {
public Cat() {
super("Cat", "walk on ground");
}
}
动物子类:Duck
public class Duck extends Animal {
public Duck() {
super("Duck", "swim on water");
}
}
抽象工厂和具体工厂
首先是抽象工厂:Factory
public interface Factory {
/**
* 抽象工厂方法,子类实现
* @return
*/
Car getCar();
/**
* 抽象方法,子类实现
* @return
*/
Animal getAnimal();
}
具体工厂1:BenzCarAndCatFactory,用于创建奔驰车和猫
public class BenzCarAndCatFactory implements Factory {
@Override
public Car getCar() {
return new BenzCar();
}
@Override
public Animal getAnimal() {
return new Cat();
}
}
具体工厂2:BMWCarAndDuckFactory,用于创建宝马车和鸭
public class BMWCarAndDuckFactory implements Factory {
@Override
public Car getCar() {
return new BMWCar();
}
@Override
public Animal getAnimal() {
return new Duck();
}
}
具体工厂3:LandRoverCarAndCatFactory,用于创建路虎车和猫
public class LandRoverCarAndCatFactory implements Factory {
@Override
public Car getCar() {
return new LandRoverCar();
}
@Override
public Animal getAnimal() {
return new Cat();
}
}
上面抽象产品家族和抽象工厂都创建完了,接下来是客户端测试代码了:
public class Client {
public static void main(String[] args) {
// 实例化一个奔驰车和猫工厂
Factory factory = new BenzCarAndCatFactory();
Car car = factory.getCar();// 得到奔驰车
Animal animal = factory.getAnimal();// 得到猫
car.drive();
animal.walk();
// 实例化一个宝马车和鸭工厂
factory = new BMWCarAndDuckFactory();
car = factory.getCar();
animal = factory.getAnimal();
car.drive();
animal.walk();
// 实例化一个路虎车和猫工厂
factory = new LandRoverCarAndCatFactory();
car = factory.getCar();
animal = factory.getAnimal();
car.drive();
animal.walk();
}
}
输出结果:
BenzCar driving on road
Cat walk on ground
BMWCar driving on road
Duck swim on water
LandRoverCar driving on road
Cat walk on ground
可以看到,各自的工厂都发挥了各自的作用,非常灵活。
抽象工厂模式优点
- 因为每个具体工厂类只负责创建产品,没有简单工厂中的逻辑判断,因此符合单一职责原则。
- 与简单工厂模式不同,抽象工厂并不使用静态工厂方法,可以形成基于继承的等级结构。
- 新增同一产品族中的产品时,只需要增加相应的具体产品和对应的具体工厂类即可。相比于简单工厂模式需要修改判断逻辑而言,抽象工厂模式更符合开-闭原则。
抽象工厂模式缺点
- 新增产品族种类(如上文类图中的Car,Animal)时,需要修改工厂接口(或者抽象工厂)及所有具体工厂,此时不符合开-闭原则。抽象工厂模式对于新的产品族符合开-闭原则而对于新的产品种类不符合开-闭原则,这一特性也被称为开-闭原则的倾斜性。
推荐阅读
设计模式(一)策略模式
设计模式(二)观察者模式
设计模式(三)装饰器模式
设计模式(四)简单工厂模式
设计模式(五)工厂方法模式