插拔式设计编程思想

插拔式设计编程

在前期使用django写项目的时候,前端向后端提交post请求的时候需要注释掉csrf校验中间件,将那行代码注释后,就无需进行校验了,那么是如何实现只注释一行代码就可以实现注释掉整个功能呢?

我们需要借助一个模块 --- import importlib,可以将字符串类型的路径转换为导入模块的语法格式

在导入模块或者py文件下的某个对象的时候,以前的书写方式是from xx.py import xx

使用importlib

import importlib
res = 'myfile.b'
ret = imprtlib.import_module(res)  # from myfile import b
# 该方法最小只能到py文件名,不能具体到文件下的某个对象
  • 需求
模拟通知消息,QQ 微信 短信等同时发送,而且可以很方便的关闭某一个通知渠道

方式一:正常思路

创建一个py文件,将每个功能定义为一个函数,再创建一个启动文件,将定义的功能导入,在启动文件中运行

myfile文件夹
- notify.py

def wechat(content):
    print(f'微信通知:{content}')


def message(content):
    print(f'短信通知:{content}')

def qq(content):
    print(f'qq通知{content}')
    
    
- start.py
import notify

def send(content):
    notify.wechat(content)
    notify.message(content)
    notify.qq(content)

if __name__ == '__main__':
    send('下课啦')

方式二:面向对象的思想,借鉴django settings中中间件的思路

  • 每一个功能独享一个py文件,放在一个文件夹下
  • 创建一个settings.py配置文件,将需要被导入的模块中的具体对象的路径以字符串的方式写入列表
  • 在存放功能的文件夹下的每个py文件都是一个功能模块,所以该文件夹就是一个包,所以就需要在该文件夹下在创建__init__.py文件,将每一个功能模块的名字都放在该py文件下
  • __init__.py文件中,通过for循环 + 鸭子类型 +字符串方法+反射就可以实现django中settings.py中只需要添加注释或者解除注释就可以实现某种功能的添加或者删除
# notify文件夹就是包
- email.py

class Email():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'email{content}')
        
- qq.py
class QQ():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'qq{content}')
        
-wechat.py

class Wechat():
    def __init__(self):
        # 调用应用接口
        pass
    def send(self,content):
        print(f'wechat{content}')
        





- settings.py

NOTIFY_LIST = [
    'notify.email.Email',
    'notify.qq.QQ',
    'notify.wechat.Wechat'
]

- __init__.py

import settings
import importlib


def send_all(content):
    for path_str in settings.NOTIFY_LIST:  #'notify.email.Email'
        module_path,class_name = path_str.rsplit('.',maxsplit=1)
        # module_path = 'notify.email'  class_name = 'Email'
        # 1 利用字符串导入模块
        module = importlib.import_module(module_path)  # from notify import email
        # 2 利用反射获取类名
        cls = getattr(module,class_name)  # Email、QQ、Wechat
        # 3 生成类的对象
        obj = cls()
        # 4 利用鸭子类型直接调用send方法
        obj.send(content)
        
        
- start.py

import notify
if __name__ == '__main__':
    notify.send_all('haha')

posted @ 2020-06-08 20:34  微信搜索-程序媛小庄  阅读(552)  评论(1编辑  收藏  举报