跳到主要内容

抽象工厂模式

抽象工厂将多个工厂方法组合在一起,以创建一系列相关或依赖对象。它保证了这一系列对象之间具有某种关联性

结构

抽象工厂示意图抽象工厂示意图

相较于 工厂方法模式,抽象工厂模式提供了对一组相关的产品(属于同一个系列且在高层主题或概念上具有相关性)对应的工厂方法的封装。

应用场景

  • 当有一系列相关的产品需要被创建,且这些产品都具有相应的变体时

优缺点

其优缺点基本上和 工厂方法模式 一致,同时还能够保证一组产品之间的关联性。

代码示例

下面的示例展示了一个抽象工厂模式的实现,其中每个工厂都产出 DoorDoorFitter 对象,且只有对应的 DoorFitter 才能安装对应的 Door

# [x] Pattern: Abstract Factory
# A class that has multiple method that creates objects of another class
# The factory class has a pair of object types

# Why we use it
# When there are interrelated dependencies with not only one object

from abc import ABC, abstractmethod
from dataclasses import dataclass


@dataclass
class Door(ABC):
width: int
height: int

def area(self):
return self.width * self.height

@abstractmethod
def _cut_material(self):
raise NotImplementedError

@abstractmethod
def _install_components(self):
raise NotImplementedError

@dataclass
class IronDoor(Door):
def _cut_material(self):
print('Cutting iron sheets')

def _install_components(self):
print('Installing iron components')

@dataclass
class DoorFitter(ABC):
name: str

def hello(self):
print(f"Hello, I'm {self.name}")

@abstractmethod
def fit_door(self, door: Door):
raise NotImplementedError

@dataclass
class IronDoorFitter(DoorFitter):

def fit_door(self, door: IronDoor):
print(f"Fitting iron door with area {door.area()}")

class DoorFactory(ABC):
@staticmethod
@abstractmethod
def make_door(self, width: int, height: int) -> Door:
raise NotImplementedError

@staticmethod
@abstractmethod
def make_fitter(self, name: str) -> DoorFitter:
raise NotImplementedError

class IronDoorFactory:
@staticmethod
def make_door(width: int, height: int) -> IronDoor:
door = IronDoor(width, height)
door._cut_material()
door._install_components()
return door

@staticmethod
def make_fitter(name: str) -> IronDoorFitter:
return IronDoorFitter(name)



def main():
iron_door = IronDoorFactory.make_door(100, 200)
print(f"Now we have an iron door with area {iron_door.area()}")
iron_fitter = IronDoorFactory.make_fitter('John')
iron_fitter.hello()
iron_fitter.fit_door(iron_door)

if __name__ == '__main__':
main()