Python 设计模式——代理模式

代理通常是指一个介于寻求方和提供方之间的中介系统。寻求发是发出请求的一方,而提供方则是根据请求提供资源的一方。
在设计模式中,代理通常是封装实际服务对象的装饰器或代理人,可以为其包装的对象提供附加功能同时无需改变对象本身的代码。其主要目的是为其他对象提供一个代理者或占位符,从而控制对实际对象的访问。

代理设计模式的主要工作:

  • 为其他对象提供代理,实现对原始对象的访问控制
  • 可以用作一个中间层或接口,以支持分布式访问
  • 通过增加代理,保护真正的组件不受意外影响

UML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# agent.py
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 __getAccount(self):
self.account = self.card
return self.account

def __hasFunds(self):
print("Bank:: Checking if Account ", self.__getAccount(), " has enough funds")
return True

def setCard(self, card):
self.card = card

def do_pay(self):
if self.__hasFunds():
print("Bank:: Paying the merhant")
return True
else:
print("Bank:: Sorry, not enough funds")
return False


class DebitCard(Payment):
def __init__(self):
self.bank = Bank()

def do_pay(self):
card = input("Proxy:: Punch in Card Number: ")
self.bank.setCard(card)
return self.bank.do_pay()


class You:
def __init__(self):
print("You:: Let's buy the Denim shirt")
self.debitCard = DebitCard()
self.isPurchased = None

def make_payment(self):
self.isPurchased = self.debitCard.do_pay()

def __del__(self):
if self.isPurchased:
print("You:: Denim shirt is Mine :-)")
else:
print("You:: I should earn more :(")


you = You()
you.make_payment()
1
2
3
4
5
6
$ python agent.py
You:: Let's buy the Denim shirt
Proxy:: Punch in Card Number: 12345
Bank:: Checking if Account 12345 has enough funds
Bank:: Paying the merhant
You:: Denim shirt is Mine :-)

关于类 You(对应 UML 图中的 client)的解释:

  • 该类用于实现客户端的行为
  • __init__() 会调用代理并将其实例化
  • make_payment() 方法表示购买动作,会在内部调用代理的付款方法

关于类 Bank(对应 UML 图中的 RealSubject)的解释:

  • 该类实际完成从顾客账户向商家划账的动作(do_pay()
  • 该类提供了多个方法来处理有关付款的一系列逻辑(__getAccount()__hasFunds()do_pay() 等)
  • 通过 setCard() 方法从代理处获取借记卡信息

关于 DebitCard 类(对应 UML 图中的 Proxy)的解释:

  • 该类用于实现代理的行为,充当真实主题(银行)的代理
  • 顾客需要付款时,无需跑去银行提款再回到商家支付,而是调用 DebitCard 的 do_pay() 方法
  • DebitCard 类在内部控制真实主题(Bank)的创建,并向银行提供借记卡的详细信息
  • Bank 对象在内部对账户进行检查并完成支付动作

代理模式的优点

  • 可以通过缓存笨重的对象或频繁访问的对象来提高应用程序的性能
  • 可以提供对于真实对象的访问授权
  • 远程代理还便于与远程服务器进行交互,并监视系统

门面模式与代理模式的比较

代理模式 门面模式
为其他对象提供代理或占位符,以控制对原始对象的访问 为类的大型子系统提供了一个简单的接口
代理对象具有与目标对象相同的接口,并保存目标对象的引用 实现了子系统之间通信和依赖性的最小化
充当客户端和被封装的对象之间的中介 提供了单一的简单接口