在实际场景中学习设计模式——单例模式
Posted 点点寒彬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在实际场景中学习设计模式——单例模式相关的知识,希望对你有一定的参考价值。
在实际场景中学习设计模式——单例模式
背景
在编码的成长过程中,慢慢的会往高级的方向发展,比如设计模式
。
但是如果单独去硬啃这些设计模式,真的是非常非常的抽象,并不容易掌握,如果能够在实际的应用中使用这些设计模式,那么学习起来非常快。
场景
本次的单例模式
是在我重构博客的过程中实际上应用的场景,也就是登录错误的控制,常规的做法是登录校验失败之后,把本次的登录数据放到数据库中,然后每次登录之前,在这个数据库中捞数据,比如一个用户名登录了5次,那么就需要把禁止用户的登录尝试,但是在这个过程中会设计到数据库的操作,如果请求量非常大,那么对数据库会产生很大的压力,假设把这个数据放到一个全局的数据中,程序读写内存的速度肯定大于数据库中的读取。
这个全局的数据,刚好就可以应用到我们的单例模式,我们的场景就是要求这个错误数据的记录,能够全局唯一,不会因为实例化导致数据被清空或者没有共享。
具体的编码
Python
的单例模式实现方法非常多,具体的请自行搜索。
我的需求是登录的错误信息要全局唯一,所以其实我并不需要非常严谨的单例模式,我只需要我的实例是共享数据的即可。
class SingleModel:
err_info =
def __new__(cls, *args, **kwargs):
obj = super(SingleModel, cls).__new__(cls, *args, **kwargs)
obj.__dict__ = cls.err_info
return obj
class ErrorTime(SingleModel):
err_time = []
def set_errtime(self, username, password, verify_code):
record_login_err_time(username, password, verify_code)
def check_err(self, username):
err_tm = self.err_time.count(username)
if err_tm >= 5:
return True
else:
return False
我这里用一个ErrorTime
的继承了基类,那么程序中所有的ErrorTime
实例都会共享数据。在使用的时候我只要这样操作即可:
err = ErrorTime()
err.set_errtime(self.username, self.passwd, self.verify_code)
err.err_time.append(self.username)
而在检查的时候,只要调用这个check_err
方法即可校验是否超限。
说明
这样的实现并不是一个非常严谨的单例模式,我只是把所有的示例共享了状态和方法,但是实际上如果你在实例化的地方加入print(id(err))
就会发现,他们ID是不一样的。
意外的收获
在构建博客的后台管理系统的时候,都需要做身份的校验,比较普遍的方法,就是做一个装饰器,在请求的方法中加上这个装饰器,先做请求的校验,但是Flask
框架有一个方法叫@before_request
,这个方法可以作为一个拦截器来拦截蓝图下的所有请求,这个方法比装饰器用起来更方便。
@CMS_VIEW.before_request
def check_login():
if request.path == '/login':
pass
else:
token = request.cookies.get('token')
if not User.check_token(token):
return render_template('CMS/login.html')
如以上代码所示,可以根据单独的请求路径来过滤校验登录token
的限制,其他所有的请求在生效之前都会校验token
,如果不符合规则,可以返回一个登录页面给他。
参考
https://www.cnblogs.com/linxiyue/p/3902256.html
https://www.cnblogs.com/huchong/p/8244279.html
以上是关于在实际场景中学习设计模式——单例模式的主要内容,如果未能解决你的问题,请参考以下文章