python多种创建工厂模式场景

MicLon原创2022年7月27日
大约 5 分钟

👉 工厂模式使用场景

  • 不清楚用户需要创建什么对象
  • 使用方法来代替new实例化对象的过程

它可以是用户自定义输入,也可以是通过接口或配置文件传入。如输入"Message",可以创建Message类的实例。

工厂模式指的是程序传入一个输入参数,自动创建所对应的对象。调用端并不需要关心类实例化的过程。基于工厂模式,可以实现可扩展、易维护的代码。

当你想扩展新增一个子类的时候,只需要关注于类本身。这样就可以遵守代码的"开闭原则",对扩展开放,对修改封闭。

👉 场景举例

下面演示一个需求场景,我们需要开发一个消息通知功能,这个消息通知需要支持多种通知方式,比如邮件、短信、微信、钉钉等。

🌱 传统的工厂模式

传统的工厂模式就是if-else多重判断,指定传参匹配指定类。

  • main.py是程序的入口,在不更改需求的前提下我们是不会去修改这个入口文件的。

  • factory.pyfactory_sender负责实例化对象。

  • channels.py就是我们开发的消息发送渠道,未来大部分工作应该专注于渠道的开发。

  • config.py是消息发送的配置项,因为不同的消息渠道有各自不同的配置。

传统模式下的一点小弊端:

我们的工作不仅限于渠道的开发,新增渠道后我们需要在factory_sender中进行手动匹配。

比如新增短信渠道就需要:elif name == "sms":

☘️ 自动导入工厂模式

在自动导入模式中,我们依然会保持上面的channels.pyconfig.py文件不变。

main.py入口文件中可以发现,原来的factory_sender方法变成了import_object。 它的作用是根据传参字符串自动导入包:

"channels.Ding"即导入channels包下面的Ding类

那么事情就变得相对简单,我们依然只需要把重心放在渠道扩展上,当新增了一个渠道Sms,自动就拥有了此类的功能。

# channels.py
……

class Sms(Notification):

    def __init__(self, config):
        ...
    
    def send_message(self, title, body, *args, **kwargs):
        print(f"Sms send message: {title} {body}")

不需要改变main.py文件,直接运行main.py主程序。

Ding send message: 警告消息 这是一条警告消息
WeChat send message: 警告消息 这是一条警告消息
Email send message: 警告消息 这是一条警告消息
Sms send message: 警告消息 这是一条警告消息

🍀 注册中心工厂模式

上述方式是通过动态导入类来实现的工厂模式,接下来继续使用动态语言特性,通过字典映射关系来注册类。

同样的,我们无需更改channels.pyconfig.py中的代码。

不难发现,所谓注册中心,其实就是字典的关系映射,将所有渠道注册到字典中,通过字典key来调用类value。

聪明的同学会说:那我岂不是还是需要手动一个个注册这些渠道?

于是我们可以在注册中心中做个自动注册

💪 总结

利用python动态语言的特性,可以开发出不一样的工厂模式来解耦实际场景。本次就分享两种工程模式的设计实现。

以上案例笔者已在一项目中体现:GitHub-simple-notifyopen in new window

Loading...