ITPub博客

首页 > 数据库 > 数据库开发技术 > python 面向对象设计模式实践篇(1)-创建型:单例模式5种方式实践

python 面向对象设计模式实践篇(1)-创建型:单例模式5种方式实践

原创 数据库开发技术 作者:程序员小钟同学 时间:2021-03-24 17:29:00 0 删除 编辑

单例模式

所属分类

  • 创建型模式

意图

  • 保证一个类的对象有且只有一个用于全局访问,没必要创建那么多的对象,来占内存,这么这个类的实现就是一个单例模式类实现。

存在缺点

  • 全局访问的情况,某处的修改会引发整体的修改。
  • 创建多对象且赋值给其他变量的时候,会增加引用计数。(垃圾回收处理)

应用场景(flask脚手架中)

  • 数据库访问对象
  • 日志操作写入对象
  • 配置文件对象
  • 第三方的插件对象
  • 数据库连接池对象
  • 缓存对象 ······

实现方式:

1)天然的单例模式之Python 的模块

原理:

  • 模块在第一次导入时,会生成.pyc文件
  • 当第二次导入时会直接从.pyc文件加载,不会再次执行模块代码

如我们的之前定义flask教授级的中间件插件的示例:首先顶一个中间件的类:

  • middleware_trace_logger.py
from common.ext.trace_logger import trace_start_log_record_handler,trace_end_log_record_handler
from flask import request
# 链路追踪中间件
class MiddlewareTraceLogger():

    def __init__(self, *args, **kwargs):
        pass

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __before_request(self):
        pass
        print('MiddlewareTraceLogger-----before_request')
        # 追踪日志初始化
        trace_start_log_record_handler()

    def __after_request(self, response):
        pass
        print('MiddlewareTraceLogger-----after_request=')
        # 追踪日志收尾
        trace_end_log_record_handler(response)
        return response

    def __teardown_request(self, exc):
        '''
        请求结束的时候提交相关的日志
        :param exc:
        :return:
        '
''
        pass

    def register_handlers(self):
        self.app.before_request(self.__before_request)
        self.app.after_request(self.__after_request)
        self.app.teardown_request(self.__teardown_request)

然后需要再:中间件的__init__执行模块导入的时候创建一个实例:

from backend.middleware.middleware_trace_logger import MiddlewareTraceLogger

middleware_trace_logger = MiddlewareTraceLogger()

middleware_trace_logger 这里就是一个单例对象。

2)元类实现的单例模式:
class MiddlewareCorsMetaclass(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super(MiddlewareCorsMetaclass, self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(MiddlewareCorsMetaclass, self).__call__(*args, **kwargs)
        return self.__instance


class MiddlewareCors(metaclass=MiddlewareCorsMetaclass):



    def __init__(self, *args, **kwargs):
        pass
        # 定义头部提交自定义的请求头
        self.token_key = 'X-Access-Token'
        # HTTP_TOKEN

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __after_request(self, response):
        # # 注册跨域
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # response.headers['Access-Control-Allow-Origin'] = '*'
        # 注意这里的方法的名称,或直接的写GET,POST,PUT,OPTIONS,DELETE
        response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS,DELETE'
        response.headers['Access-Control-Allow-Headers'] = '*'
        # response.headers['Access-Control-Allow-Headers'] = '*222222222'
        # 这个地方不能直接的写* 号, 当前端发起跨域  解决axios出现的Request header is not allowed by Access-Control-Allow-Headers in preflight response
        # 需要明确支持的头部信息
        # login2323?redirect=%2F:1 XMLHttpRequest cannot load http://ikp5c9.natappfree.cc/sys/login. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response
        # 奇葩的UC 浏览器
        # 奇葩的UC 浏览器--注意一点 涉及到跨域的时候,涉及自定义头部信息的时候,都需要再次加上
        allow_headers = '*,School-Teacher-Token,school-teacher-token,T-Access-Token,x-access-token,Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
        response.headers['Access-Control-Allow-Headers'] = allow_headers

        # response.headers['Access-Control-Allow-Headers'] =response.headers['Access-Control-Allow-Headers']
        return response



    def register_handlers(self):
        self.app.after_request(self.__after_request)

middleware_cors1 = MiddlewareCors()
middleware_cors2 = MiddlewareCors()

print(middleware_cors1 is middleware_cors2)# True
3)__new__的构造方法的实现:
class MiddlewareCors():

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(MiddlewareCors, cls).__new__(cls)
        return cls._instance

    def __init__(self, *args, **kwargs):
        pass
        # 定义头部提交自定义的请求头
        self.token_key = 'X-Access-Token'
        # HTTP_TOKEN

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __after_request(self, response):
        # # 注册跨域
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # response.headers['Access-Control-Allow-Origin'] = '*'
        # 注意这里的方法的名称,或直接的写GET,POST,PUT,OPTIONS,DELETE
        response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS,DELETE'
        response.headers['Access-Control-Allow-Headers'] = '*'
        # response.headers['Access-Control-Allow-Headers'] = '*222222222'
        # 这个地方不能直接的写* 号, 当前端发起跨域  解决axios出现的Request header is not allowed by Access-Control-Allow-Headers in preflight response
        # 需要明确支持的头部信息
        # login2323?redirect=%2F:1 XMLHttpRequest cannot load http://ikp5c9.natappfree.cc/sys/login. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response
        # 奇葩的UC 浏览器
        # 奇葩的UC 浏览器--注意一点 涉及到跨域的时候,涉及自定义头部信息的时候,都需要再次加上
        allow_headers = '*,School-Teacher-Token,school-teacher-token,T-Access-Token,x-access-token,Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
        response.headers['Access-Control-Allow-Headers'] = allow_headers

        # response.headers['Access-Control-Allow-Headers'] =response.headers['Access-Control-Allow-Headers']
        return response



    def register_handlers(self):
        self.app.after_request(self.__after_request)

middleware_cors1 = MiddlewareCors()
middleware_cors2 = MiddlewareCors()

print(middleware_cors1 is middleware_cors2)
4)装饰形式的实现:
from flask import request
from common.exc import ForbiddenException, InvalidTokenException,ExpiredTokenException
from common.ext.jwt import Auth



def MiddlewareCorssingleton(cls):
    _instance = {}
    def inner(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]
    return inner


@MiddlewareCorssingleton
class MiddlewareCors():

    def __init__(self, *args, **kwargs):
        pass
        # 定义头部提交自定义的请求头
        self.token_key = 'X-Access-Token'
        # HTTP_TOKEN

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __after_request(self, response):
        # # 注册跨域
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # response.headers['Access-Control-Allow-Origin'] = '*'
        # 注意这里的方法的名称,或直接的写GET,POST,PUT,OPTIONS,DELETE
        response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS,DELETE'
        response.headers['Access-Control-Allow-Headers'] = '*'
        # response.headers['Access-Control-Allow-Headers'] = '*222222222'
        # 这个地方不能直接的写* 号, 当前端发起跨域  解决axios出现的Request header is not allowed by Access-Control-Allow-Headers in preflight response
        # 需要明确支持的头部信息
        # login2323?redirect=%2F:1 XMLHttpRequest cannot load http://ikp5c9.natappfree.cc/sys/login. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response
        # 奇葩的UC 浏览器
        # 奇葩的UC 浏览器--注意一点 涉及到跨域的时候,涉及自定义头部信息的时候,都需要再次加上
        allow_headers = '*,School-Teacher-Token,school-teacher-token,T-Access-Token,x-access-token,Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
        response.headers['Access-Control-Allow-Headers'] = allow_headers

        # response.headers['Access-Control-Allow-Headers'] =response.headers['Access-Control-Allow-Headers']
        return response



    def register_handlers(self):
        self.app.after_request(self.__after_request)

middleware_cors1 = MiddlewareCors()
middleware_cors2 = MiddlewareCors()

print(middleware_cors1 is middleware_cors2) # True
5)类的装饰形式的实现:
class MiddlewareCorssClassSingleton:
    def __init__(self, cls):
        self._cls = cls
        self._instance = {}

    def __call__(self, *args):
        if self._cls not in self._instance:
            self._instance[self._cls] = self._cls(*args)
        return self._instance[self._cls]


@MiddlewareCorssClassSingleton
class MiddlewareCors():

    def __init__(self, *args, **kwargs):
        pass
        # 定义头部提交自定义的请求头
        self.token_key = 'X-Access-Token'
        # HTTP_TOKEN

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __after_request(self, response):
        # # 注册跨域
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # response.headers['Access-Control-Allow-Origin'] = '*'
        # 注意这里的方法的名称,或直接的写GET,POST,PUT,OPTIONS,DELETE
        response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS,DELETE'
        response.headers['Access-Control-Allow-Headers'] = '*'
        # response.headers['Access-Control-Allow-Headers'] = '*222222222'
        # 这个地方不能直接的写* 号, 当前端发起跨域  解决axios出现的Request header is not allowed by Access-Control-Allow-Headers in preflight response
        # 需要明确支持的头部信息
        # login2323?redirect=%2F:1 XMLHttpRequest cannot load http://ikp5c9.natappfree.cc/sys/login. Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response
        # 奇葩的UC 浏览器
        # 奇葩的UC 浏览器--注意一点 涉及到跨域的时候,涉及自定义头部信息的时候,都需要再次加上
        allow_headers = '*,School-Teacher-Token,school-teacher-token,T-Access-Token,x-access-token,Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
        response.headers['Access-Control-Allow-Headers'] = allow_headers

        # response.headers['Access-Control-Allow-Headers'] =response.headers['Access-Control-Allow-Headers']
        return response



    def register_handlers(self):
        self.app.after_request(self.__after_request)

middleware_cors1 = MiddlewareCors()
middleware_cors2 = MiddlewareCors()

print(middleware_cors1 is middleware_cors2) # True

资料参考来源

https://blog.csdn.net/qdPython/article/details/108869599

个人其他博客地址

简书:https://www.jianshu.com/u/d6960089b087

掘金:https://juejin.cn/user/2963939079225608

小钟同学 | 文 【原创】| QQ:308711822

  • 1:本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。
  • 2:关于文章内容,有部分内容参考自互联网,如有链接会声明标注;如没有及时标注备注的链接的,如有侵权请联系,我会立即删除处理哟。


原文作者:程序员小钟同学;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-02-20

  • 博文量
    224
  • 访问量
    111698