设计模式(六)抽象工厂模式

设计模式(六)抽象工厂模式_第1张图片

导读:前文设计模式(五)工厂方法模式介绍了工厂方法模式,本篇开始介绍抽象工厂模式,继续优化工厂方法模式,更好的满足开闭原则和可扩展性。

抽象工厂模式解决的问题

在工厂方法模式中,我们已经知道其缺点:只能对同一类的产品进行创建,不能对不同类型的产品簇类型进行创建。

抽象工厂模式可以解决这样的问题。

抽象工厂模式定义

这个模式可以创建产品的家族。提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户端使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品时什么。

抽象工厂模式UML类图

设计模式(六)抽象工厂模式_第2张图片
简单工厂模式UML图

抽象工厂模式角色划分

  • 抽象产品(或者产品接口),如上文类图中的AbstractProductA,AbstractProductB;
  • 具体产品,如ProductA1,ProductB1;
  • 抽象工厂(或者工厂接口),如AbstractFactory;
  • 具体工厂,如果ConcreteFactory1,ConcreteFactory2;
  • 产品族,如AbstractProductAe产品族中有产品:ProductA1,ProductA2;

抽象工厂使用示例代码

抽象产品家族A:以汽车家族产品为例

设计模式(六)抽象工厂模式_第3张图片
汽车产品家族

首先是家族产品基类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)时,需要修改工厂接口(或者抽象工厂)及所有具体工厂,此时不符合开-闭原则。抽象工厂模式对于新的产品族符合开-闭原则而对于新的产品种类不符合开-闭原则,这一特性也被称为开-闭原则的倾斜性。

推荐阅读

设计模式(一)策略模式
设计模式(二)观察者模式
设计模式(三)装饰器模式
设计模式(四)简单工厂模式
设计模式(五)工厂方法模式

设计模式(六)抽象工厂模式_第4张图片

你可能感兴趣的:(设计模式(六)抽象工厂模式)