设计模式之代理模式¶
过去都是假的,回忆是一条没有归途的路,以往的一切春天是无法复原的。
Author: 李东阳
1、什么是代理模式¶
内容¶
为其他对象提供一种代理,来控制对这个对象的访问。
应用场景:¶
-
远程代理:为远程的对象提供代理
-
虚代理:根据需要创建很大的对象
-
保护代理:控制对原始对象的访问,用于对象有不同的访问权限时
角色¶
-
抽象实体(Subject)
-
实体(Real Subject)
-
代理(Proxy)
2、三种代理模式¶
2.1、远程代理¶
隐藏对象位于远程地址空间的事实 例如写入数据,而数据库不在本地,需要远程访问。隐藏数据库不在本地的事实,使用代理进行远程存储。
2.2、虚代理¶
为了节省资源开销,在功能没有被真正调用时,就不运行。 例如浏览器中的无图模式,不显示图片,等你真正需要查看某张时,点击才会真正加载图像,不点击时,只会告诉你,此处是一张图像,并不显示
2.3、保护代理¶
为了区分用户权限而设置的代理。 例如普通用户只有访问权限,而开发人员有写入权限。
3、代码实现¶
远程代理不做过多解释,这里主要介绍虚代理和保护代理。
3.1、虚代理的实现¶
举个例子:
大多数项目中都会用到文件读取这个功能,我们就拿它举例子好了,
每个人应该都玩游戏,但是你们有没有发现一个现象。就是越炫酷或者大型的游戏,它的启动加载就会越慢。之所以启动得慢,大家应该知道其实是它在加载一些游戏所需要的资源文件等等。其实这里就用到了虚代理,它这些资源肯定不是一次性加载完成的,如果是那你可以等上几个小时了。游戏启动时只加载它的一些启动界面等一些资源,后面的皮肤啊,什么的,肯定是用户什么时候需要在什么时候加载。
文件读写实现:
from abc import ABCMeta, abstractmethod
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self): # 读取文件内容方法
pass
@abstractmethod
def set_content(self, content): # 修改文件内容方法
pass
class RealSubject(Subject):
def __init__(self, filename):
self.filename = filename
print('读取文件内容!')
with open(self.filename, 'r', encoding='utf-8') as f:
self.content = f.read() # 可以看得到,这里一初始化就读取文件内容到内存中了,如果后面用户没有读取或者修改,那不白白浪费内存吗?
def get_content(self):
return self.content
def set_content(self, content):
with open(self.filename, 'w', encoding='utf-8') as f:
f.write(content)
subj = RealSubject('test.txt')
"""
读取文件内容!
"""
这种一上来就加载不必要的资源到内存中的方法是不可取得,大家尽量避免。
虚代理实现文件读取:
from abc import ABCMeta, abstractmethod
# 抽象实体
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self):
pass
@abstractmethod
def set_content(self, content):
pass
# 实体
class RealSubject(Subject):
def __init__(self, filename):
self.filename = filename
print('读取文件内容!')
with open(self.filename, 'r', encoding='utf-8') as f:
self.content = f.read()
def get_content(self):
return self.content
def set_content(self, content):
with open(self.filename, 'w', encoding='utf-8') as f:
f.write(content)
# 虚代理
class VirtualProxy(Subject):
def __init__(self, filename):
self.filename = filename
self.subj = None
def get_content(self):
if not self.subj:
self.subj = RealSubject(self.filename) # 返回实体对象
return self.subj.get_content()
def set_content(self, content):
if not self.subj:
self.subj = RealSubject(self.filename)
return self.subj.set_content(content)
subj = VirtualProxy('test.txt')
print(subj.get_content()) # 当我们调用读取文件内容函数时才会将文件读取到内存
3.2、保护代理的实现¶
这里代理就让用户只有读文件的权限,不能写
代码实现:
from abc import ABCMeta, abstractmethod
# 抽象实体
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self):
pass
@abstractmethod
def set_content(self, content):
pass
# 实体
class RealSubject(Subject):
def __init__(self, filename):
self.filename = filename
print('读取文件内容!')
with open(self.filename, 'r', encoding='utf-8') as f:
self.content = f.read()
def get_content(self):
return self.content
def set_content(self, content):
with open(self.filename, 'w', encoding='utf-8') as f:
f.write(content)
# 保护代理
class ProtectedSubject(Subject):
def __init__(self, filename):
self.subj = RealSubject(filename)
def get_content(self):
return self.subj.get_content()
def set_content(self, content):
raise PermissionError('无写入权限!')
subj = ProtectedSubject('test.txt')
print(subj.get_content())
subj.set_content('abc')