Proxy
动机(Motivation)
- 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),
直接访问会给使用者、或者系统结构带来很多麻烦。 - 如何在不失去透明操作对象的同事来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
模式定义
为其他对象提供一种代理以控制(隔离,使用接口)对这对象的访问。
——《设计模式》GoF
要点总结
- Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。
应用案例
常见的代理类型如下所示。
- 在使用私有网络或云搭建一个分布式系统时。在分布式系统中,一些对象存在于本地内 存中,一些对象存在于远程计算机的内存中。如果我们不想本地代码关心两者之间的区 别,那么可以创建一个远程代理来隐藏/封装,使得应用的分布式性质透明化。
- 因过早创建计算成本较高的对象导致应用遭受性能问题之时。使用虚拟代理引入懒初始 化,仅在真正需要对象之时才创建,能够明显提高性能。
- 用于检查一个用户是否有足够权限来访问某个信息片段。如果应用要处理敏感信息(例 如,医疗数据),我们会希望确保用户在被准许之后才能访问/修改数据。一个保护/防护 代理可以处理所有安全相关的行为。
- 应用(或库、工具集、框架等)使用多线程,而我们希望把线程安全的重任从客户端代码转移到应用。这种情况下,可以创建一个智能代理,对客户端隐藏线程安全的复杂性。
- 对象关系映射(Object-Relational Mapping,ORM)API也是一个如何使用远程代理的例子。包括Django在内的许多流行Web框架使用一个ORM来提供类OOP的关系型数据库访问。 ORM是关系型数据库的代理,数据库可以部署在任意地方,本地或远程服务器都可以。
例子
通过代理SensitiveInfoProxy
来访问信息SensitiveInfo
,在添加新用户时只有密码正确,才能进行操作 。
# -*- coding:utf-8 -*-
class SensitiveInfo(object):
def __init__(self):
self.user = ['nick', 'tom', 'ben', 'mike']
def get_user(self):
print('There are {} user: {}'.format(len(self.user), '; '.join(self.user)))
def add_user(self, user):
self.user.append(user)
print('Added user {}'.format(user))
class SensitiveInfoProxy(object):
def __init__(self):
self.sensitive_info_obj = SensitiveInfo()
self.secret = '123456'
def get_user(self):
self.sensitive_info_obj.get_user()
def add_user(self, user):
sec = input('what is the secret(str type)?')
if type(sec) != str:
print('secret should be str type')
if sec == self.secret:
self.sensitive_info_obj.add_user(user)
else:
print('secret is wrong!')
if __name__ == '__main__':
sensitive_info_proxy = SensitiveInfoProxy()
while True:
print('1: get user list. 2: add user. 3:exit')
key = input('choose option: ')
if key == 1:
sensitive_info_proxy.get_user()
elif key == 2:
name = input('choose username: ')
sensitive_info_proxy.add_user(name)
elif key == 3:
exit()
else:
print('wrong option')
网友评论