欢迎来到Cecilia陈的博客

孤独,是人一生最好的修行。

21 参考中间件,实现可插拔式设计

一、前言

什么是可插拔式设计?

在我们前面学习的django的内容,在django框架中,我们学习到了中间件,中间件是干嘛的,都还记得把!!

中间件是当请求来的时候,全局的对每一个request进行一个验证,我们都知道在Django的中间件中,有7个默认的中间件,而当一个request来的时候,这个request要依次经过每一个中间件的校验,当这个request对应的response走的时候,又要按照中间件列表的顺序进行倒叙执行中间件

在我们最开始用form表单提交数据的时候,我们好像是要把一个叫csrf的中间件给注释掉,然后form表单才能去提交post请求,也就是说当注释掉这个叫csrf的中间件的时候,request请求来的时候,这个request就不会经过这个中间件的校验了,而当我们把这个csrf的中间件注释解开的时候,我们发现request请求有经过这个中间件的校验了。这就叫可插拔式设计

二、可插拔式需要用到的方法

1. 可插拔式设计的代码,一定要是面向对象的
2.用到一个
3.用到反射getattr()

三、实例

我们现在有一个公司,现在公司有一个需求,因为今天是10月的最后一天,公司准备给每一个工作人员通过qq、手机短信、微信的方式,给工作人员发三太难短信,

然后,到11月份的月底,公司只想通过微信,qq的方式来发送信息了,这该怎么样设计一个可插拔是的程序呢?---根据django中间件的思想

1.我们先用面向对象来写着三个发消息的共功能
# 面向对象的鸭子类型
# 只要长得像,就是鸭子类型
# 就是有很多个类,但是这些个类都具有同样的方法名,但是呢?它的方法名实现的功能不一样,就是鸭子类型

# QQ 消息
class QQ:
    # 实例化类的时候触发
    def __init__(self,name):
        self.name = name
        
    # 对象的绑定方法
    # 也是鸭子类型的方法
    def send_msg(self,content):
        print('QQ今天是10月的最后一天,请好好{}'.format(content))

        
        
# 微信 消息
class Wechat:
    # 对象实例化的时候触发
    def __init__(self,name):
        self.name = name
        
    # 鸭子类型的方法,对象的绑定方法   
    def send_msg(self,content):
        print('Wechat今天是10月的最后一天,请好好{}'.format(content))        
        
# Phone 短信
class Phone:
    def __init__(self,name):
        self.name = name
    
    # 鸭子类型
    def send_msg(self,content):
        print('Phone今天是10月的最后一天,请好好{}'.format(content))       

从上面我们写的类中,三种发送消息的类,可以看到send_msg就是鸭子类型的方法,

我们将上面的每一个类都放在不同的.py文件里

为什么放在一个包里呢?因为在settings配置里面。我们要导入这几个文件,导入一个文件他就是一个模块,那作为一个模块,当然要放在包里了,__init__.py文件里,from msg_bag import *

那这三个类都写好了,我们知道django中间件是则settings里配置了一个列表,这个列表就是放着一个个字符串一行的类,

那这里,我们也将这三个类放在setting文件中,当然首先的自己新建一个settings配置文件啦

# settings.py
FUNC_LIST  = [
    'msg_bag.phone.Phone',
    'msg_bag.qq.QQ',
    'msg_bag.wechat.Wechat',
]
# 启动文件

import setting # 将配置文件导进来
import importlib # 将这个模块导入


def run(content):
    # 循环settings配置文件里的类的模块列表
    '''
    FUNC_LIST  = [
    'msg_bag.phone.Phone',
    'msg_bag.qq.QQ',
    'msg_bag.wechat.Wechat',
    '''
    for func in setting.FUNC_LIST:
        # 将每一个字符串拿出来,然后根据.切割,从末尾切割一个
        model,class_name = func.rsplit('.',maxsplit=1)
        print(model) # msg_bag.phone \ msg_bag.qq \ msg_bag.wechat
        print(class_name) # Phone \ QQ \ Wechat

        # 利用importlib模块
        mod = importlib.import_module(model)
        '''
         等同于 
         form msg_bag import phone
         form msg_bag import qq
         form msg_bag import wechat
        '''

        # 通过反射class_name是不是mod的类,然后取值赋给class_obj
        class_obj = getattr(mod, class_name)
        
        # 通过类去调用对象的绑定方法,将类自己传给send_msg
        class_obj.send_msg(class_obj,content)


run('开开心心')
posted @ 2019-10-31 22:45  Cecilia陈  阅读(1096)  评论(0编辑  收藏  举报