代理模式目录
代理模式
概念
- 代理就是一个中间系统
- 代理模式关键在于对外屏蔽真实对象
- 通过代购可以类比一下
演员与经纪人的例子来理解一下:
class Actor(object):
def __init__(self):
self.is_busy = False
def occupied(self):
self.is_busy = True
print(type(self).__name__, '正在拍电影')
def available(self):
self.is_busy = False
print(type(self).__name__, '正在休息')
def get_status(self):
return self.is_busy
class Agent(object):
def __init__(self):
self.principal = None
def work(self):
# 给他一个演员
self.actor = Actor()
# 如果在忙就休息,如果在休息就忙起来
if self.actor.get_status():
self.actor.occupied()
else:
self.actor.available()
代理维护一个引用,代理通过这个引用访问实际对象。代理也负责创建和删除真实业务。
实现:
再来一个例子实现一个规模较大的代理:
付款系统
- 用户行为由类User表示
- 为了购买衣服,User类提供pay方法
- 魔法方法__init__调用代理并将其实例化
- pay方法在内部调用代理的方法进行付款
- 付款成功,返回__del__方法
class User(object):
def __init__(self):
self.debit_card = DebitCard()
self.is_purchased = None
def pay(self, card_id):
self.is_purchased = self.debit_card.do_pay(card_id)
def __del__(self):
if self.is_purchased:
print('购买成功')
else:
print('购买失败')
# 主题是付款,是一个抽象基类,
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def do_pay(self):
pass
# 真实主题银行类
class Bank(Payment):
def __init__(self):
self.card = None
self.account = None
def __get_acount(self):
self.account = self.card
return self.account
def __has_funds(self):
print('找到卡号:', self.__get_acount())
return True
def set_card(self, card):
self.card = card
def do_pay(self):
if self.__has_funds():
print('扣款成功')
return True
else:
print('扣款失败')
return False
# 代理
class DebitCard(Payment):
def __init__(self):
self.bank = Bank()
def do_pay(self, card_id):
self.bank.set_card(card_id)
return self.bank.do_pay()
user = User()
user.pay('123456')
代理有什么用?
- 代理可以通过缓存要频繁访问的对象来提高性能
- 可以比作:代购
代理和门面区别
代理模式 | 门面模式 |
---|---|
给其他对象提供了代理或者占位符,以控制对原始对象的访问 | 为大型子系统提供接口 |
代理对象和目标对象接口一致,并有对目标的引用 | 实现子系统之间通信和依赖的最小化 |
充当客户端和被封装对象的中介 | 提供单一的简单的接口 |
常见问题
- 装饰器和代理区别:
- 装饰器给正在运行时的对象添加行为,代理是控制对象的访问。代理不是动态的,装饰器是动态的。
- 代理模式缺点:
- 增加响应时间,比如代理如果结构不好,就会增加时间。所以取决于代理写的好不好
- 客户端可以独立访问真实主题吗?
- 可以,但是代理模式可以提供许多优势:虚拟、远程等。
- 代理能给自己添加功能吗?
- 可以,而且无需改对象的代码。代理和真是主题可以实现相同的接口