设计模式第三谈:抽象工厂模式

这篇文章将会介绍23种设计模式的抽象工厂模式。

1、什么是抽象工厂模式

“四人帮”编写的《设计模式-可复用面相对象软件的基础》一书中给出定义是:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

1.1 抽象工厂模式和工厂方法模式的区别

谈起抽象工厂模式,是不是想到工厂方法模式呢?我们来回顾一下工厂方法模式的定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。从定义上来看,这两种模式有些相似,它们的区别是什么呢?

简单来说,就是工厂方法的产品单一,而抽象工厂的产品多样,也就是说,工厂方法只有一个抽象产品类、一个具体产品类,每个具体工厂创建一个具体产品类,而抽象工厂可以有多个产品抽象类、多个具体的产品类,每个具体工厂可以创建多个具体产品类。

也可以这么理解:工厂方法模式只考虑下图中的一个产品等级,每个工厂生产单一的产品;抽象工厂模式考虑一个产品族,每个工厂生产多个产品。

在这里插入图片描述
看到这,应该对于这两种模式的区别有了大概的印象,接下来通过一个具体场景来加深下理解。

2、Python代码实现

上一篇文章中,介绍了汽车工厂生产汽车的场景,在这呢,咱们把这个场景继续细化:一个汽车由许多零配件组成,包括:轮胎、门等。那么,细化后的场景如何用Python实现呢?大体思路是这样的:

  • 定义汽车零配件的抽象类,然后,每个类型的汽车具体实现汽车零配件
  • 定义抽象工厂类,规定这些零配件的组装顺序
  • 实现具体工厂类,实现创建零配件,并依照指定的组装顺序,制造汽车

2.1 定义轮胎抽象类及其具体实现

  • 轮胎抽象类:WheelAbstract.py
# coding: utf-8

from abc import ABC, abstractmethod


class WheelAbstract(ABC):
    """汽车轮子抽象类"""

    def say(self):
        """轮子操作"""
        pass

  • 宝马轮胎具体类:WheelBMW.py
# coding: utf-8

from .WheelAbstract import WheelAbstract


class WheelBMW(WheelAbstract):
    """宝马汽车的轮子"""

    def say(self):
        print("这是宝马汽车的轮子")

  • 奔驰轮胎具体实现类:WheelBENZ.py
# coding: utf-8

from .WheelAbstract import WheelAbstract


class WheelBENZ(WheelAbstract):
    """奔驰汽车轮子"""

    def say(self):
        print("这是奔驰汽车的轮子")

2.2 定义车门抽象类及其具体实现

  • 车门抽象类:DoorAbstract.py
# coding: utf-8

from abc import ABC, abstractmethod


class DoorAbstract(ABC):
    """汽车门抽象类"""

    @abstractmethod
    def say(self):
        pass
  • 宝马汽车车门具体类:DoorBMW.py
# coding: utf-8

from .DoorAbstract import DoorAbstract


class DoorBMW(DoorAbstract):
    """宝马汽车门"""

    def say(self):
        print("这是宝马汽车的门")
  • 奔驰汽车车门具体类:DoorBENZ.py
# coding: utf-8

from .DoorAbstract import DoorAbstract


class DoorBENZ(DoorAbstract):
    """奔驰汽车门"""

    def say(self):
        print("这是奔驰汽车的门")

2.3 定义工厂抽象类及其具体实现

  • 工厂抽象类:FactoryAbstract.py
# coding: utf-8

from __future__ import annotations

from abc import ABC, abstractmethod

from .DoorAbstract import DoorAbstract
from .WheelAbstract import WheelAbstract


class CarFactoryAbstract(ABC):
    """定义汽车工程抽象类"""

    @abstractmethod
    def create_wheel(self) -> WheelAbstract:
        """创建轮子"""
        pass

    @abstractmethod
    def create_door(self) -> DoorAbstract:
        """创建车门"""
        pass

    def create(self):
        """定义零配件组装顺序"""
        
        car_wheel = self.create_wheel()
        car_door = self.create_door()

        car_wheel.say()
        car_door.say()
  • 宝马汽车工厂具体类:CarFactoryBMW.py
# coding: utf-8

from .CarFactoryAbstract import CarFactoryAbstract
from .DoorBMW import DoorBMW
from .WheelBMW import WheelBMW


class CarFactoryBMW(CarFactoryAbstract):
    """宝马汽车工厂"""

    def create_door(self):
        return DoorBMW()

    def create_wheel(self):
        return WheelBMW()
  • 奔驰汽车工厂具体类:CarFactoryBENZ.py
# coding: utf-8

from .CarFactoryAbstract import CarFactoryAbstract
from .DoorBENZ import DoorBENZ
from .WheelBENZ import WheelBENZ


class CarFactoryBENZ(CarFactoryAbstract):
    """奔驰汽车工厂"""

    def create_door(self):
        return DoorBENZ()

    def create_wheel(self):
        return WheelBENZ()

2.4 抽象工厂类测试

  • abstract_factory_example.py
# coding: utf-8

from AbstractFactory.CarFactoryBMW import CarFactoryBMW
from AbstractFactory.CarFactoryBENZ import CarFactoryBENZ


if __name__ == '__main__':
    car_factory_bmw = CarFactoryBMW()
    car_factory_bmw.create()

    car_factory_benz = CarFactoryBENZ()
    car_factory_benz.create()

输出结果:

这是宝马汽车的轮子
这是宝马汽车的门
这是奔驰汽车的轮子
这是奔驰汽车的门

注意:在abstract_factory_example文件中并没有引入任何具体的类,而是引入了抽象类。

在上面这个例子中,DoorAbstractWheelAbstract实现了一系列相关或依赖对象CarFactoryAbstract则实现了创建一系列相关或依赖对象的接口create_door()create_wheel()方法并没有指定具体的类,而是放在具体的实现类CarFactoryBMWCarFactoryBENZ中实现了具体的类。

3、抽象工厂模式的结构

抽象工厂模式组成元素包括:一个工厂抽象类、多个工厂具体类、多个产品抽象类、多个产品具体类:

  • 工厂抽象类:声明了一个创建抽象产品的操作接口
  • 具体工厂类:实现创建具体产品对象的操作
  • 产品抽象类:为一类产品对象声明一个接口
  • 具体产品类:为一个将被对应的抽象工厂创建的对象

抽象工厂模式的类图如下图所示:

在这里插入图片描述

4、抽象工厂模式的适用性

抽象工厂模式可应用于以下情况:

  • 当需要多个产品系列中的一个来配置时,如:生成汽车中的宝马汽车
  • 一个系统需要由一系列相关的产品时,如:汽车中的轮胎、车门、后视镜
  • 当提供一个产品类库,且具有同样的接口,而客户端不依赖产品实例的创建细节和内部机构

5、抽象工厂方法模式的优缺点

优点:

  • 抽象模式隔离了具体产品类的生产,使得客户不知道什么被创建
  • 当一个产品族中的多个对象被设计在一起工作时,能够保证客户端始终只使用一个产品族中的对象
  • 增加新的具体工厂和具体产品类很方便,无需修改已有系统,符合”开闭规则“

缺点:

  • 产品族扩展比较困难,需修改抽象工厂类和所有的具体工厂类,对”开闭原则“的支持成倾斜性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值