class Door():
def open_door(self):
print("打开门")
这个类有一个 open_door
方法,负责打开门,接下来,要为这个门进行升级,
为它安装一个门禁,只有刷卡才能打开,设计并实现一个新的类, ProxyDoor
。
class ProxyDoor():
def __init__(self):
self.real_object = Door()
def open_door(self):
print("先刷卡")
self.real_object.open_door()
ProxyDoor
并不是 Door
的子类,它内部有一个 real_object
属性,类型是 Door
,
ProxyDoor
类也有一个 open_door
方法,与 Door
里的一模一样,
最后一步,实现一个 open_the_door
函数。
def open_the_door():
door = ProxyDoor()
door.open_door()
open_the_door()
先刷卡 打开门
现在,开始理解代理模式是如何工作的。
Door
是服务对象ProxyDoor
是代理对象open_the_door
是客户端
真正实现了开门这个服务的,是Door这个类,但是客户端在使用时,
却并没有直接使用 Door
这个类,而是用了代理对象 ProxyDoor
。
代理对象对 open_door
这个方法做出了限制,必须先刷卡,然后将开门的这个要求提供给了 Door
,
ProxyDoor
一边接收客户端的请求,一边对请求做了限制性检查并将请求传递给真正的能够提供服务的 Door
。
因此,在代理对象中,必须维护一个服务对象,就本例而言,在 ProxyDoor
对象中必须维护一个 real_object
对象。
所谓客户端,你可以理解为,谁使用代理对象,谁就是客户端。
代理模式的作用和好处
代理模式可以实现松耦合,它将核心逻辑与可能附加的功能分离, 代码的模块化特性使得维护和扩展主要逻辑功能变得更容易。
在代理模式中,核心功能是由服务对象提供的,这使得你可以专注于核心逻辑, 代理对象只是在它的基础之上附加了一些新的功能。
代理模式和增加子类的对比
就上面的例子而言,其实有别的办法来实现相同的效果,比如增加一个子类:
class CardDoor(Door):
def open_door(self):
print("先刷卡")
super(CardDoor, self).open_door()
def open_the_door():
door = CardDoor()
door.open_door()
open_the_door()
先刷卡 打开门
在子类 CardDoor
中重写 open_door
方法就可以了,程序最终的执行结果与代理模式是相同的。
如果你能想到这一层,说明你对面向对象编程已经掌握的非常熟练了。 这的确是一个难以回答的问题,这也是很多讲解设计模式的文章刻意回避的问题。
曾尝试着来回答一下,增加一个子类,固然可以实现相同的效果,但与代理模式相比较, 刷卡这个限制仍然被写在了服务对象里,而代理模式追求的是让服务对象更专一的实现其核心逻辑, 由代理对象为服务对象增加额外的功能。
先不去比较这两种模式哪个更好,而是结合实际情况,决定你追求哪种效果, 如果代理模式所提供的附加功能存在不确定性,可能在某一天消失或者变动频繁, 或者附加功能与服务对象的核心逻辑联系不紧密,本身倾向于使用代理模式当附加功能出现变化时, 修改代理对象就可以了。
增加子类,侧重的是描述定义一个新的类别,对象,代理模式侧重的是为服务对象提供附加的功能, 增加子类时,有可能会增加新的属性,而代理模式不改变服务对象的任何属性和方法, 仅仅是在中间代理时做一些访问限制,提供一些附加功能。