(八)python 设计模式 --- 代理模式

版权声明:本文为博主原创文章,转载文章须附上文章来源与作者。 https://blog.csdn.net/ChangerJJLee/article/details/86682294

定义

  • 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
  • 著名的代理模式例子为引用计数(英语:reference counting)指针对象。
    当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少存储器用量。典型作法是创建一个复杂对象及多个代理者,每个代理者会引用到原本的复杂对象。而作用在代理者的运算会转送到原本对象。一旦所有的代理者都不存在时,复杂对象会被移除。

代理模式的优点和应用场景
优点:

  1. 责任清晰:符合单一职责原则,使被代理对象实现真实业务逻辑,而非本职责的事务,交由代理完成;
  2. 扩展性高:面对被代理对象可能会有的改变,代理模式在不改变其对外接口的情况下,可以实现最大程度的扩展;
  3. 保证主题对象的处理逻辑:代理可以通过检查参数的方式,保证主题对象的处理逻辑输入在理想范围内。

应用场景:

  1. 针对某特定对象进行功能和增强性扩展。如IP防火墙,接口访问权限,远程访问代理,中间件等技术的应用;
  2. 对被代理对象进行保护。如大流量代理,安全代理等;
  3. 减轻被代理对象的负载。如接口分流等。

代理模式的缺点

  • 可能会降低整体业务的处理效率和速度。
  • 增加代码维护成本。

常见的代理模式的缺点

  • 虚拟代理(VirtualPRoxy):推迟真正所需对象实例化时间.在需要真正的对象工作之前, 如果代理对象能够处理, 那么暂时不需要真正对象来处理.比如图片延迟加载,虚拟占位,通过延迟对象实例化来减缓系统资源的消耗

  • 安全代理(ProtectionProxy):控制真实对象访问时的权限,比如某系统管理员A,利用终端访问令牌,访问终端代理,代理通过该令牌从数据库获得该令牌所拥有可操作的指令列表B,从而A每操作的一个指令都会检验是否存在于列表B,若存在则代理应用root或者其他用户 去执行该指令并将结果返回,该终端代理扮演的就是安全代理的角色。

  • 智能代理(intelligent agent):是定期地收集信息或执行服务的程序,它不需要人工干预,具有高度智能性和自主学习性,可以根据用户定义的准则,主动地通过智能化代理服务器为用户搜集最感兴趣的信息,然后利用代理通信协议把加工过的信息按时推送给用户,并能推测出用户的意图,自主制订、调整和执行工作计划。比如定时任务Crontab

  • 远程代理(Remote Proxy):本地服务通过网络请求远程服务。为了实现本地到远程的通信,我们需要实现网络通信,处理其中可能的异常。为良好的代码设计和可维护性,我们将网络通信部分隐藏起来,只暴露给本地服务一个接口,通过该接口即可访问远程服务提供的功能,而不必过多关心通信部分的细节。比如Django的ORM

数据懒加载

class _LazyProperty(object):

    def __init__(self, func):
        print(5*'*'+' _Lazy --> __init__ '+ 5*'*')
        self.func = func

    def __get__(self, instance, _cls):
        print(5*'*'+' _Lazy --> __get__ (instance: %s _cls: %s) '%(str(instance), str(_cls)) + 5*'*')
        val = self.func(instance)
        setattr(instance, self.func.__name__, val)
        return val


class UserInfo(object):
    def __init__(self, _name):
        print(5*'*'+' UserInfo --> __init__ '+ 5*'*')
        self._name = None

    @_LazyProperty
    def name(self):
        print(5*'*'+' UserInfo --> name <从数据库获取用户姓名> '+ 5*'*')
        self._name = user_info_db_obj['name']
        return self._name


if __name__ == '__main__':
    # 模拟数据库
    user_info_db_obj = dict(name='Lee')
    # 获取用户信息
    u = UserInfo('Lee')
    print(u.name)
    print(u.name)
    print(u.name)
    print(u.name)
    
# -*- coding: utf-8 -*-
from wsgiref.simple_server import make_server
from functools import wraps


def acl(func):

    @wraps(func)
    def wrap(_request, _response, *args, **kwargs):
        try:
            white_list = ['127.0.0.2']
            _ip = _request['REMOTE_ADDR']
            if _ip in white_list:
                return func(_request, _response)
            else:
                raise IOError('access from %s is not in white'%(_ip))
        except Exception as e:
            return error_handle(str(e), _response)
    return wrap


def error_handle(error_info, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return error_info


@acl
def some_handle(request, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return 'Query String Is %s' % str(request['QUERY_STRING'])


if __name__ == '__main__':
    httpd = make_server('', 8000, some_handle)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()
access from 127.0.0.1 is not in white

猜你喜欢

转载自blog.csdn.net/ChangerJJLee/article/details/86682294
今日推荐