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

Posted 码农阿焦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式第三谈:抽象工厂模式相关的知识,希望对你有一定的参考价值。

这篇文章将会介绍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、抽象工厂方法模式的优缺点

优点:

  • 抽象模式隔离了具体产品类的生产,使得客户不知道什么被创建

  • 当一个产品族中的多个对象被设计在一起工作时,能够保证客户端始终只使用一个产品族中的对象

  • 增加新的具体工厂和具体产品类很方便,无需修改已有系统,符合”开闭规则“

缺点:

  • 产品族扩展比较困难,需修改抽象工厂类和所有的具体工厂类,对”开闭原则“的支持成倾斜性

以上是关于设计模式第三谈:抽象工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式抽象工厂模式 ( 简介 | 适用场景 | 优缺点 | 产品等级结构和产品族 | 代码示例 )

设计模式学习一简单工厂模式

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式 创建者模式 工厂设计模式 -- 抽象工厂设计模式介绍和实现

设计模式:抽象工厂模式

设计模式11:抽象工厂模式