00:文章简介
记录python中2个常用的设计模式:单例模式和工厂模式。
01:单例模式
Singleton Pattern 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
当你希望在整个系统中,某个类只能出现一个实例时,可以使用单例模式。
class Singleton:
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = object.__new__(cls)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1, obj2)
# <__main__.Singleton object at 0x10f012d90> <__main__.Singleton object at 0x10f012d90>
这种设计模式在应用程序读取配置文件时很有效果,多个应用程序读取配置文件,只能获取同一份配置文件。
02:工厂模式
工厂模式是一个在软件开发中用来创建对象的设计模式。
在面向对象编程中,术语工厂
表示一个负责创建其他类型对象的类。
通常情况下,作为一个工厂的类有一个对象以及与它关联的多个方法,使用者使用某些参数调用此方法后,工厂会根据需求创建对应的对象,然后将它们返回使用者。
举例:现实生活中我们有造鞋子的工厂,我们需要鞋子的时候,只需要告诉他我要什么样的鞋子,工厂就会给我们造什么样的鞋子,我们并不需要关心造鞋子的过程。
2.1:工厂模式的优点
- 松耦合,对象的创建独立于类的实现
- 使用者无需了解创建对象的类,只需要知道需要传递的接口、方法和参数,就能够创建所需要的对象
- 容易扩展工厂添加其他类型对象的创建,使用者只需要关心参数的变化就可以了
2.2:工厂模式的使用场景
- 不知道用户想要创建什么样的对象
- 当你想要在创建类与支持创建对象的类(工厂类)之间创建一个可扩展的关联
2.3:示例
-
工厂中包含
-
造鞋类
- Blue和Red,输入大小就可以创造出对应颜色的鞋子
-
工厂类
- get_shoes,判断用户想要什么颜色的鞋子,将不同颜色的需求转发到不同的
流水线
- get_shoes,判断用户想要什么颜色的鞋子,将不同颜色的需求转发到不同的
-
-
用户包含
- 调用工厂类,输入鞋子的颜色和大小,就可以获得对应的鞋子,而不用关心它是怎么产生的
代码
class Blue:
def __init__(self, size):
print("This is a pair of blue shoes, size {}".format(size))
class Red:
def __init__(self, size):
print("This is a pair of red shoes, size {}".format(size))
class Factory:
@classmethod
def get_shoes(cls, colour, size):
if colour == "Blue":
return Blue(size)
if colour == "Red":
return Red(size)
if __name__ == '__main__':
factory = Factory()
shoes = factory.get_shoes("Red", "36")
# This is a pair of red shoes, size 36
03:工厂模式的应用
在收集CMDB资产信息时,一开始需要获取的数据很少,但随着规模的扩大,需要获取的数据越来越多,维护的人越来越多,每个人写的收集代码各个不同,为了统一方法的接口,也为了后续维护人员方便阅读,所以使用了工厂模式+反射+约束
来设计收集资产信息的客户端程序。
3.1:程序结构
├── app.py # 主程序
├── lib # 主程序调用的库,也就是所有接口存放位置
│ ├── __init__.py
│ └── plugins # 接口文件夹
│ ├── __init__.py
│ ├── basic.py # 所有接口的基类
│ └── memory.py # 获取内存信息接口
└── settings.py # 主程序配置文件
3.2:主程序
使用importlib和settings配置文件,动态导入需要的插件接口方法
import importlib
from settings import PLUGIN_CLASS_DICT
def run():
for key, path in PLUGIN_CLASS_DICT.items():
module_path, class_name = path.rsplit('.', maxsplit=1)
module = importlib.import_module(module_path)
cls = getattr(module, class_name)
plugin_object = cls()
info = plugin_object.process()
print(key, info)
if __name__ == '__main__':
run()
3.3:配置文件
保存插件的位置和插件的名称
PLUGIN_CLASS_DICT = {
"memory": "lib.plugins.memory.MemoryPlugin"
}
3.4:接口基类
利用NotImplementedError
约束子类,必须实现process
接口方法
class BasePlugin:
"""
所有插件功能的基类,用于做约束,约束子类中必须实现process功能。
"""
def process(self):
raise NotImplementedError()
3.5:接口示例
不管内容如何实现,必须提供process接口返回需要的信息
from .basic import BasePlugin
class MemoryPlugin(BasePlugin):
"""
采集网卡信息
"""
def process(self):
return {'memory': '16G'}
3.6:运行测试
# 返回值
memory {'memory': '16G'}
评论区