python多种创建工厂模式场景
👉 工厂模式使用场景
- 不清楚用户需要创建什么对象
- 使用方法来代替new实例化对象的过程
它可以是用户自定义输入,也可以是通过接口或配置文件传入。如输入"Message",可以创建Message类的实例。
工厂模式指的是程序传入一个输入参数,自动创建所对应的对象。调用端并不需要关心类实例化的过程。基于工厂模式,可以实现可扩展、易维护的代码。
当你想扩展新增一个子类的时候,只需要关注于类本身。这样就可以遵守代码的"开闭原则",对扩展开放,对修改封闭。
👉 场景举例
下面演示一个需求场景,我们需要开发一个消息通知功能,这个消息通知需要支持多种通知方式,比如邮件、短信、微信、钉钉等。
🌱 传统的工厂模式
传统的工厂模式就是if-else多重判断,指定传参匹配指定类。
main.py
是程序的入口,在不更改需求的前提下我们是不会去修改这个入口文件的。factory.py
中factory_sender负责实例化对象。channels.py
就是我们开发的消息发送渠道,未来大部分工作应该专注于渠道的开发。config.py
是消息发送的配置项,因为不同的消息渠道有各自不同的配置。
传统模式下的一点小弊端:
我们的工作不仅限于渠道的开发,新增渠道后我们需要在factory_sender中进行手动匹配。
比如新增短信渠道就需要:elif name == "sms":
☘️ 自动导入工厂模式
在自动导入模式中,我们依然会保持上面的channels.py和config.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.py
和config.py
中的代码。
不难发现,所谓注册中心,其实就是字典的关系映射,将所有渠道注册到字典中,通过字典key来调用类value。
聪明的同学会说:那我岂不是还是需要手动一个个注册这些渠道?
于是我们可以在注册中心中做个自动注册
💪 总结
利用python动态语言的特性,可以开发出不一样的工厂模式来解耦实际场景。本次就分享两种工程模式的设计实现。
以上案例笔者已在一项目中体现:GitHub-simple-notify