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

news2024/9/28 2:22:34

文章目录

    • 从一个例子谈起
    • 抽象工厂模式的组件构成
    • 根据抽象工厂模式实现
    • 抽象工厂模式的缺点

抽象工厂模式属于创建型设计模式,一般用来创建复杂的对象,这种对象由许多小对象组成,这些小对象都属于某个特定的类别。


从一个例子谈起

常见的例子是在家具商城中,有家具产品:椅子和沙发等等;这些产品同时有中式、日式等风格。如果用户期望一批日式风格的家具,你就得给它一批日式风格的家具。这里中式风格的家具生产厂就是一个复杂对象,而具体的中式椅子就是小对象。
假设现在客户端代码希望通过调用代码,生产出一批家具,这批家具必须风格一致。没有使用这种设计模式前,我们可能会这样实现代码。

class ChinaSofa:
    @classmethod
    def create_sofa(cls):
        return ChinaSofa()

    def __str__(self):
        return "china style sofa"

class ChinaChair:
    @classmethod
    def create_chair(cls):
        return ChinaChair()

    def __str__(self):
        return "china style chair"

class JapanSofa:
    @classmethod
    def create_sofa(cls):
        return JapanSofa()

    def __str__(self):
        return "japan style sofa"

class JapanChair:
    @classmethod
    def create_chair(cls):
        return JapanChair()

    def __str__(self):
        return "japan style chair"


def main():
     print(ChinaSofa.create_sofa())
     print(ChinaChair.create_chair())

main()

这里 main 函数可以理解为客户端代码,我们看到在生产某种风格的产品时,代码需要知道用 ChinaSofa 类和 ChinaChair

print(ChinaSofa.create_sofa())
print(ChinaChair.create_chair())

这里有两个明显的缺点:

  1. 如果在产品非常多的情况下,使用者可能会在代码中混入其他风格的类来生成产品。这意味着需要使用者很大的心智负担
  2. 如果现在增加一种欧式风格的沙发和椅子,我们就需要修改 main 函数的代码,即代码间存在耦合

作为客户端代码的开发者会更希望自己不需要关注生产中式风格的椅子用哪个类、日式风格的椅子又是哪个类。对他来说理想的行为应该是:

client factory 未来都制作中式风格的家具给我 我要把椅子 制作中式风格的椅子 我要张沙发 制作中式风格的沙发 client factory

基于这样的设想,可以预见我们的main 函数将是这样的:

def main():
	# 风格的选择可以作为配置文件或者函数参数传入
    factory=ChinaStyle() 
    print(factory.create_sofa())
    print(factory.create_chair())

在这种调用形式下,我们解决了上面提到的两个缺点,那么该如何实现呢?

抽象工厂模式的组件构成

在进入实现之前,需要了解下抽象工厂模式由哪些组件组成:

  1. 抽象工厂

    抽象工厂是一个高层次的蓝图,它定义了创建相关对象族的一系列规则,而无需指定具体的类。它声明了一系列方法,每个方法负责创建一种特定类型的对象,并确保具体工厂遵循一个通用接口,从而提供一种一致的方式来生成相关的对象集。

  2. 具体的工厂

    具体工厂实现抽象工厂定义的接口函数。它包含在一个系列中创建特定对象实例的逻辑。一般会存在多个具体工厂,每个工厂都是为生产一个不同的相关对象系列而量身定制的。

  3. 抽象的产品

    抽象产品通过定义一组通用方法或属性来表示相关对象的系列。它是一个系列中所有具体产品都必须遵守的抽象或接口类型,并为具体产品的互换使用提供了统一的方式。

  4. 具体的产品

    它们是由具体工厂创建的对象的实际实例。它们实现抽象产品中声明的方法,确保族内的一致性,并属于相关对象的特定类别或族。

  5. 客户端

    客户利用抽象工厂创建对象系列,无需指定具体类型,并通过抽象产品提供的抽象接口与对象交互。客户可通过更改具体工厂实例,灵活地在对象系列之间无缝切换。

具体的调用逻辑

抽象产品
具体产品1 class
具体产品2 class
客户端
抽象工厂
具体工厂1
具体工厂2

实际上我们可以忽略实现抽象产品

根据抽象工厂模式实现

根据上面的组件介绍,我们可以对前文的例子进行对号入座:

  1. 客户端根据期望,用特定的工厂类生成工厂实例。这些工厂类继承自一个抽象的工厂类;
  2. 抽象工厂类定义了一系列可以生成产品实例的抽象函数,因此特定的工厂类通过重写这些函数,使得他们可以生成自己系列的产品对象

根据期望的行为给出接口的关系图:
在这里插入图片描述
接下来就是照着这张图实现:

from abc import ABC, abstractmethod

class FurnitureFactory(ABC):
    @abstractmethod
    def create_sofa(self):
        pass

    @abstractmethod
    def create_chair(self):
        pass

class ChinaStyle(FurnitureFactory):
    def create_sofa(self):
        return ChinaStyleSofa()

    def create_chair(self):
        return ChinaStyleChair()


class JapanStyle(FurnitureFactory):
    def create_sofa(self):
        return JapanStyleSofa()

    def create_chair(self):
        return JapanStyleChair()

class Sofa(ABC):
    def can_sleep():
        return "the man can sleep on it"

class ChinaStyleSofa(Sofa):
    def __str__(self):
        return "china style sofa"

class JapanStyleSofa():
    def __str__(self):
        return "japan style sofa"

class Chair(ABC):
    def can_sit():
        return "the man can sit down"

class ChinaStyleChair(Chair):
    def __str__(self):
        return "china style chair"

class JapanStyleChair(Chair):
    def __str__(self):
        return "japan style chair"

def main():
    factory = ChinaStyle()
    print(factory.create_sofa())
    print(factory.create_chair())

main()

抽象工厂模式的缺点

  • 对比这两段代码,可以发现这种设计模式下的代码更加复杂,它实现了很多的抽象工厂和抽象产品接口,而在这个简单的例子中显得有些多余。因此对于简单的系统而言,这种模式有时并不适合,它带来的代码复杂度大过了它带来的优点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1980662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot企业人力资源管理系统-计算机毕业设计源码29005

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

【Windows 11 】Missing Customize FOlder OPtion 文件夹右键自定义消失

突然发现win11 无法修改文件夹的默认图标原来是因为没有自定义选项了。微软有人问,大神解决了这个问题 右键缺少的是自定义这个标签 自定义长这样子: HKEY_CLASSES_ROOT\Directory\shellex\PropertySheetHandlers 下已经有了 {ef43ecfe-2ab9-4632-bf21…

uniapp 让同一个子组件重新加载

给子组件添加不同的 “key” 值,当 key 值改变时,Vue 会认为这是一个不同的组件,并重新创建它

C语言——贪吃蛇游戏

用c语言在window环境的控制台中模拟写出贪吃蛇小游戏。 一.要实现的基本的功能 如下: 贪吃蛇的地图绘制 贪吃蛇吃食物的功能(方向控制蛇的动作) 贪吃蛇撞墙死亡判断 贪吃蛇撞自己死亡判断 计算得分 贪吃蛇的速度 暂停游戏 二 贪吃蛇的铺垫准…

【HTML入门】第二十二课 - 【实战】做一个注册页面

这一小节,我们继续纯HTML标签的使用,这一节我们做一个 注册页面。说到注册页面,其实大家的网站都大同小异,所以我们就不四处去找设计图了,我们自己想一个注册页面,想想注册页面都应该有哪些元素&#xff0c…

探究全局代理是什么?有什么作用?

今天,我们来聊聊一个经常被提及但很多人不太了解的概念——全局代理。那么,全局代理到底是什么?它有什么用?以及如何正确使用呢?接下来,小编就带大家一探究竟! 什么是全局代理? 通俗…

360联合国内15个最强大模型推出“AI助手”碾压GPT4o!全球首部《人工智能法案》正式生效!|AI日报

文章推荐 GPT-4o版「Her」终于来了!英伟达股价两周内下跌23%!|AI日报 Apple Intelligence将在今年10月推出?AI毛绒玩具BubblePal回答人类幼崽十万个为什么!|AI日报 今日热点 360放大招:联合…

Rodin来袭,AI建模再填猛将

AI建模,AI绘图,Rodin,人工智能,Stable Diffusion, Stable Diffusion,midjourney,Bing AI等人工智能在绘图界掀起腥风血雨,外界一致认为将取代原画师,但是真正的原画师却感觉良好,他们认为:“AI…

Unable to clear output directory

Bug信息 Exception in thread "main" java.io.IOException: Unable to clear output directory hdfs://xxx/warehouse/hive/xx.db/xxx prior to writing to itat org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelationCommand.deleteMatchingPart…

“智绘未来,慧聚南京”2024南京智博会

“智慧城市”一个听起来颇具未来感的词汇,在如今的南京市已逐步成为现实。在5G、物联网、人工智能、大数据等新一代信息技术的支撑下,南京市正逐渐变成一个可感知可“思考”的智能体,智慧社区、智慧医疗、智慧交通、智慧政务等数字化、智能化…

Flink-StarRocks详解:第六部分-即席查询大案例解析(第56天)

系列文章目录 数仓场景:即席查询案例 6.1 场景介绍 6.2 方案架构 6.3 方案特点 6.4 操作流程 6.4.1 步骤一:创建MySQL源数据表 6.4.2 步骤二:创建StarRocks表 6.4.3 步骤三:执行Flink任务,启动数据流 6.4.4 步骤四&am…

gemini2相机和宇树雷达L1的使用注意点

gemini2相机: 官方资料:Gemini2深度相机 (yahboom.com) 目前深度这一块智能提供某一点的深度数据,没有提供某一点的世界坐标,虽然网上有文章说是可以计算 已知深度图,获得某个像素点的三维坐标_深度图如何知道特征点的3d坐标-CS…

Windows系统下安装mujoco环境的教程【原创】

在学习Mujoco仿真的过程中,我先前是在linux系统下进行的研究与学习,今天来试试看在windows系统中安装mujoco仿真环境。 先前在linux中的一些关于mujoco学习记录的博客:Mujoco仿真【xml文件的学习 3】_mujoco打开xml文件-CSDN博客 下面开始wi…

怎么防止电脑上的重要视频被录屏

加密软件防录屏是通过一系列技术手段来防止视频内容在播放过程中被非法录制和传播。 一、视频加密技术 高强度加密算法:使用如AES256位等高强度加密算法对视频内容进行加密,确保视频在传输和存储过程中的安全性。这样,即使视频被录制&#…

黑科技,教你同时在一个电脑上同时开启多个微信

我们右键微信图标选择属性 然后 将这个目标复制下来 然后 我们新建一个文本文件 然后 在记事本中 输入 start 后面跟着微信目标内容 但是需要注意 双引号要换一下位置 换到盘符后面 例如 我的目标是 “D:\Program Files (x86)\Tencent\WeChat\WeChat.exe” 但是 我要输入 st…

第19课 Scratch入门篇:摇骰子

摇骰子 🎲 故事背景: 有一颗神奇的骰子,随机变换不同的样子,让我们一起来设计一款属于自己的骰子,和自己身边的人比比,看看谁的数字大! 程序原理: 骰子数字的变化,只要…

javascript 的奇技巧淫一

1 、使用 !! 转换为布尔值 // 使用双重否定快速将任何值转换为布尔值。 let a !!1; // true let b !!0; // false2 、 短 If-Else 的三元运算符\ let price 100; let message price > 200 ? "Expensive" : "Cheap";3、 默认函数参数 // 设置函数…

引领未来:埃隆·马斯克与拉里·佩奇论道企业开放合作的创新之路——张驰咨询

开放式创新是企业在产品研发和商业化活动中,充分整合全社会的智力、资源,以最大限度调动社会各界智力资源,从而实现互利共赢的一种创新模式。它打破了传统封闭式创新的界限,使企业能够像使用内部资源一样借用外部资源进行创新。 …

字体文件的引用与使用 -------css

1、字体文件的全局引用&#xff08;app.vue的<style>&#xff09; <style> font-face {font-family: "PingFangSC";src: url("./assets/fonts/PingFangSC.ttf");font-weight: normal;font-style: normal; } </style> 2、字体文件在组件…

算法力扣刷题记录 六十五【17.电话号码的字母组合】

前言 回溯章节第三篇&#xff1a;前两篇做了两道组合题目&#xff0c;练习回溯模版。 本文 记录 六十五【17.电话号码的字母组合】。 一、题目阅读 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映…