python之工厂设计模式

一、简介

工厂设计模式的优点:

1
2
3
4
松耦合,即对象的创建可以独立于类的实现
客户端无需了解创建对象的类,但是照样可以使用它来创建对象。它只需要知道需要传递的接口、方法和参数,就能够创建所需类型的对象了
可用轻松地在工厂中添加其他类来创建其他类型的对象,而这无需更改客户端代码。最简单的情况下,客户端只需要传递另一个参数就可以了
工厂还可以重用现有对象。但是客户端直接创建对象的话,总是创建一个新的对象

工厂设计模式3中变体:

1
2
3
简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑
工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则交由子类决定
抽象工厂模式:抽象工厂是一个能创建一系列相关的对象二无需指定/公开其具体的接口。该模式能够提供其他工厂的对象,在其内部创建其他对象

二、简单工厂模式

简单工厂模式包含如下角色:  

1
2
3
Factory:工厂角色   CarFactory
Product:抽象产品角色     CarStore
ConcreateProduct:具体产品角色  YilanteCar/SounataCar ...

模式分析:

1
2
3
将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
在调用工厂类的工厂方法时,由于工厂方法可以是静态方法,使用起来很方便,可通过类名直接调用,而且只需要传入一个简单的参数即可,在实际开发中,还可以在调用时将所传入的参数保存在XML等格式的配置文件中,修改参数时无须修改任何源代码。
简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。

简单工厂模式的优点  

1
2
3
工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

简单工厂模式的缺点  

1
2
3
4
由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
简单工厂模式如果使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构

模式适用环境

1
2
工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

总结:

1
2
3
简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。
简单工厂模式适用情况包括:工厂类负责创建的对象比较少;客户端只知道传入工厂类的参数,对于如何创建对象不关心。

三、工厂模式  

工厂模式定义:

1
2
3
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
工厂方法模式能够封装具体类型的实例化,抽象的 Creator 提供了一个创建对象的工厂方法。在抽象的 Creator 中,任何其他实现的方法,都可能使用到这个方法所制造出来的产品,但只有子类真正实现这个工厂方法并创建产品。
子类创建出具体产品。 创建者类不需要知道实际创建的产品是哪一个,选择了使用了哪个子类,自然也就决定了实际创建的产品是什么。

 工厂方法模式优点:

1
2
3
工厂方法集中的在一个地方创建对象,使对象的跟踪变得更容易。
工厂方法模式可以帮助我们将产品的实现从使用中解耦。如果增加产品或者改变产品的实现,Creator 并不会收到影响。
使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

简单工厂和工厂方法之间的差异:

1
简单工厂把全部的事情在一个地方处理完了(CarFactory),而工厂方法是创建了一个框架,让子类去决定如何实现。比如在工厂方法中,order() 方法提供了一般的框架用来创建 car,order() 方法依赖工厂方法创建具体类,并制造出实际的 car。而制造什么样的 car 是通过继承 CarStore来实现的。 但 简单工厂 只是把对象封装起来,并不具备工厂方法的弹性。  

四、抽象工厂模式

抽象工厂模式与工厂模式与简单工厂模式的关系: 

1
当抽象工厂模式中每一个具体工厂类只创建一个产品对象(工厂只造枪),也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂(只有步枪工厂)来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

抽象工厂的优缺点:

1
2
3
客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。 所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
 
另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点:

1
在添加新的产品对象比较困难,因为要对所有的工厂都添加类似产品 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。

参考链接:https://xionchen.github.io/2017/02/25/python-patterns_01/  

posted @   百衲本  阅读(152)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
cnblogs_post_body { color: black; font: 0.875em/1.5em "微软雅黑" , "PTSans" , "Arial" ,sans-serif; font-size: 15px; } cnblogs_post_body h1 { text-align:center; background: #333366; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 23px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h2 { text-align:center; background: #006699; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 20px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } cnblogs_post_body h3 { background: #2B6695; border-radius: 6px 6px 6px 6px; box-shadow: 0 0 0 1px #5F5A4B, 1px 1px 6px 1px rgba(10, 10, 0, 0.5); color: #FFFFFF; font-family: "微软雅黑" , "宋体" , "黑体" ,Arial; font-size: 18px; font-weight: bold; height: 25px; line-height: 25px; margin: 18px 0 !important; padding: 8px 0 5px 5px; text-shadow: 2px 2px 3px #222222; } 回到顶部 博客侧边栏 回到顶部 页首代码 回到顶部 页脚代码
点击右上角即可分享
微信分享提示