前言
GOF设计模式分三大类:
- 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
- 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
- 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。
一、抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)
-
定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。即将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产。
-
解决问题:如何设计一个能够创建一系列产品对象的工厂?(每一个具体工厂可以生产属于一个产品族的所有产品)
-
使用场景:
- 与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,而是负责创建一族产品。
-
相关术语:
- 产品等级结构:产品等级结构即产品的继承结构,例如一个抽象类是电视机,其子类有A品牌电视机、B品牌电视机、C品牌电视机等等
- 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。例如X工厂生产的电视机、电冰箱、空调等等
-
优点:
- 与工厂方法模式相比,减少了系统中类的个数。能够保证客户端始终只使用同一个产品族中的对象。
- 对于增加新的产品族,抽象工厂模式很好地支持了开闭原则。
-
缺点:
- 对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。
二、抽象工厂模式示例
使用抽象工厂模式来设计界面皮肤库,一种是绿色风格界面,一种是蓝色风格界面
python"># 模块 skins.py
"""抽象产品簇"""class Button:"""抽象产品按钮"""def display(self):raise NotImplementedErrorclass TextField:"""抽象产品文本框"""def display(self):raise NotImplementedErrorclass ComboBox:"""抽象产品组合框"""def display(self):raise NotImplementedError"""具体产品簇Spring"""class SpringButton(Button):def display(self):print("显示绿色按钮")class SpringTextField(TextField):def display(self):print("显示绿色文本框")class SpringComboBox(ComboBox):def display(self):print("显示绿色组合框")"""具体产品簇Summer"""class SummerButton(Button):def display(self):print("显示蓝色按钮")class SummerTextField(TextField):def display(self):print("显示蓝色文本框")class SummerComboBox(ComboBox):def display(self):print("显示蓝色组合框")"""抽象工厂"""class SkinFactory:def create_button(self) -> Button:raise NotImplementedErrordef create_text_field(self) -> TextField:raise NotImplementedErrordef create_combo_box(self) -> ComboBox:raise NotImplementedError"""具体工厂"""class SpringSkinFactory(SkinFactory):def create_button(self):return SpringButton()def create_text_field(self):return SpringTextField()def create_combo_box(self):return SpringComboBox()class SummerSkinFactory(SkinFactory):def create_button(self):return SummerButton()def create_text_field(self):return SummerTextField()def create_combo_box(self):return SummerComboBox()
引入配置文件config.json
{"class_name": "SummerSkinFactory"
}
通过工具类JsonUtil读取配置文件
python"># 模块 utils.py
from pathlib import Path
import jsonclass JsonUtil:@staticmethoddef get_value(key: str):path = Path("config.json")contents = path.read_text(encoding="utf-8")conf = json.loads(contents)return conf.get(key, None)
客户端代码
python">import skins
from utils import JsonUtilclass_name = JsonUtil.get_value("class_name")
klass = getattr(skins, class_name, None)
if klass:factory: skins.SkinFactory = klass()bt = factory.create_button()tf = factory.create_text_field()cb = factory.create_combo_box()bt.display()tf.display()cb.display()### 输出结果
显示蓝色按钮
显示蓝色文本框
显示蓝色组合框
三、抽象工厂模式在Django框架中的应用
Django 的数据库后端系统允许你使用不同的数据库系统(如 PostgreSQL、MySQL、SQLite 等),并且可以很容易地在它们之间切换,而不需要改变你的模型代码。
python"># Django项目的配置文件 settings.py
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
}
Django 的数据库后端系统定义了一个抽象的接口,不同的数据库引擎(如 django.db.backends.postgresql
, django.db.backends.mysql
, django.db.backends.sqlite3
等)实现了这个接口。这些数据库引擎就是具体工厂,它们根据数据库的类型创建对应的数据库连接和操作对象。
python"># 抽象工厂 django.db.backends.base.base
class BaseDatabaseWrapper:"""Represent a database connection."""# ...# 具体工厂 django.db.backends.mysql.base
class DatabaseWrapper(BaseDatabaseWrapper):vendor = "mysql"# ...# 具体工厂 django.db.backends.postgresql.base
class DatabaseWrapper(BaseDatabaseWrapper):vendor = "postgresql"# ...# 具体工厂 django.db.backends.sqlite3.base
class DatabaseWrapper(BaseDatabaseWrapper):vendor = "sqlite"# ...
您正在阅读的是《设计模式Python版》专栏!关注不迷路~