设计模式Python版 抽象工厂模式

文章目录


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)

  • 定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。即将一些相关的产品组成一个"产品族",由同一个工厂来统一生产。

  • 解决问题:如何设计一个能够创建一系列产品对象的工厂?(每一个具体工厂可以生产属于一个产品族的所有产品

  • 使用场景:

    • 与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,而是负责创建一族产品。
  • 相关术语:

    • 产品等级结构:产品等级结构即产品的继承结构,例如一个抽象类是电视机,其子类有A品牌电视机、B品牌电视机、C品牌电视机等等
    • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。例如X工厂生产的电视机、电冰箱、空调等等
  • 优点:

    • 与工厂方法模式相比,减少了系统中类的个数。能够保证客户端始终只使用同一个产品族中的对象
    • 对于增加新的产品族,抽象工厂模式很好地支持了开闭原则。
  • 缺点:

    • 对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了开闭原则。

二、抽象工厂模式示例

使用抽象工厂模式来设计界面皮肤库,一种是绿色风格界面,一种是蓝色风格界面

python 复制代码
# 模块 skins.py
"""抽象产品簇"""

class Button:
    """抽象产品按钮"""

    def display(self):
        raise NotImplementedError


class TextField:
    """抽象产品文本框"""

    def display(self):
        raise NotImplementedError


class 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 NotImplementedError

    def create_text_field(self) -> TextField:
        raise NotImplementedError

    def 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

json 复制代码
{
    "class_name": "SummerSkinFactory"
}

通过工具类JsonUtil读取配置文件

python 复制代码
# 模块 utils.py
from pathlib import Path
import json

class JsonUtil:
    @staticmethod
    def 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 JsonUtil

class_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版》专栏!关注不迷路~

相关推荐
几道之旅9 分钟前
pytdx能否下载期货数据呢?
python
vyuvyucd13 分钟前
MPPI算法实战:机器人避障与仿真
python
计算机徐师兄13 分钟前
Python基于Flask的广东旅游数据分析系统(附源码,文档说明)
python·flask·旅游数据分析·广东旅游数据分析系统·python广东数据分析系统·python广东旅游数据分析·python旅游数据分析系统
jarreyer15 分钟前
数据项目分析标准化流程
开发语言·python·机器学习
GZKPeng18 分钟前
pytorch +cuda成功安装后, torch.cuda.is_available 是False
人工智能·pytorch·python
我的xiaodoujiao19 分钟前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 39--生成 Allure测试报告
python·学习·测试工具·pytest
陈小桔23 分钟前
logging模块-python
开发语言·python
水中加点糖26 分钟前
RagFlow实现多模态搜索(文、图、视频)与(关键字/相似度)搜索原理(二)
python·ai·音视频·knn·ragflow·多模态搜索·相似度搜索
贾宝玉的玉宝贾28 分钟前
FreeSWITCH 简单图形化界面52 - 拨号应用 Answer 介绍
python·django·voip·freeswitch·sip·ippbx·jssip
Hello.Reader28 分钟前
PyFlink JAR、Python 包、requirements、虚拟环境、模型文件,远程集群怎么一次搞定?
java·python·jar