设计模式第三谈:抽象工厂模式
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
文件中并没有引入任何具体的类,而是引入了抽象类。
在上面这个例子中,DoorAbstract
和WheelAbstract
实现了一系列相关或依赖对象
;CarFactoryAbstract
则实现了创建一系列相关或依赖对象的接口
,create_door()
和create_wheel()
方法并没有指定具体的类
,而是放在具体的实现类CarFactoryBMW
、CarFactoryBENZ
中实现了具体的类。
3、抽象工厂模式的结构
抽象工厂模式组成元素包括:一个工厂抽象类、多个工厂具体类、多个产品抽象类、多个产品具体类:
工厂抽象类:声明了一个创建抽象产品的操作接口
具体工厂类:实现创建具体产品对象的操作
产品抽象类:为一类产品对象声明一个接口
具体产品类:为一个将被对应的抽象工厂创建的对象
抽象工厂模式的类图如下图所示:
4、抽象工厂模式的适用性
抽象工厂
模式可应用于以下情况:
当需要多个产品系列中的一个来配置时,如:生成汽车中的宝马汽车
一个系统需要一系列相关的产品时,如:汽车中的轮胎、车门、后视镜
当提供一个产品类库,且具有同样的接口,而客户端不依赖产品实例的创建细节和内部机构
5、抽象工厂方法模式的优缺点
优点:
抽象模式隔离了具体产品类的生产,使得客户不知道什么被创建
当一个产品族中的多个对象被设计在一起工作时,能够保证客户端始终只使用一个产品族中的对象
增加新的具体工厂和具体产品类很方便,无需修改已有系统,符合”开闭规则“
缺点:
产品族扩展比较困难,需修改抽象工厂类和所有的具体工厂类,对”开闭原则“的支持成倾斜性
以上是关于设计模式第三谈:抽象工厂模式的主要内容,如果未能解决你的问题,请参考以下文章
设计模式抽象工厂模式 ( 简介 | 适用场景 | 优缺点 | 产品等级结构和产品族 | 代码示例 )