阿里资深架构师解析python-访问者模式
访问者模式
访问者模式,是行为型设计模式之一。访问者模式是一种将数据操作与数据结构分离的设计模式,它可以算是 23 中设计模式中最复杂的一个,但它的使用频率并不是很高,大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那你就是需要使用它了。 访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象的类都拥有一个 accept 方法用来接受访问者对象的访问。访问者是一个接口,它拥有一个 visit 方法,这个方法对访问到的对象结构中不同类型的元素做出不同的处理。在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施 accept 方法,在每一个元素的 accept 方法中会调用访问者的 visit 方法,从而使访问者得以处理对象结构的每一个元素,我们可以针对对象结构设计不同的访问者类来完成不同的操作,达到区别对待的效果。
定义及使用场景
定义: 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。 可以对定义这么理解:有这么一个操作,它是作用于一些元素之上的,而这些元素属于某一个对象结构。同时这个操作是在不改变各元素类的前提下,在这个前提下定义新操作是访问者模式精髓中的精髓。
使用场景: (1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作。 (2)需要对一个对象结构中的对象进行很多不同的且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
UML图
代码示例
#encoding=utf-8
#
#by panda
#访问模式
def printInfo(info):
print unicode(info, 'utf-8').encode('gbk')
#基本数据结构:
class Person():
def Accept(self, visitor):
pass
class Man(Person):
type = '男人'
def Accept(self, visitor):
visitor.GetManConclusion(self)
class Woman(Person):
type = '女人'
def Accept(self, visitor):
visitor.GetWomanConclusion(self)
#基于数据结构的操作
class Action():
def GetManConclusion(self, person):
pass
def GetWomanConclusion(self, person):
pass
class Success(Action):
type = '成功'
def GetManConclusion(self, person):
printInfo('%s %s时,背后多半有一个伟大的女人' %(person.type, self.type))
def GetWomanConclusion(self, person):
printInfo('%s %s时,背后大多有一个不成功的男人' %(person.type, self.type))
class Failing(Action):
type = '失败'
def GetManConclusion(self, person):
printInfo('%s %s时,闷头喝酒,谁也不用劝' %(person.type, self.type))
def GetWomanConclusion(self, person):
printInfo('%s %s时,眼泪汪汪,谁也劝不了' %(person.type, self.type))
class Love(Action):
type = '恋爱'
def GetManConclusion(self, person):
printInfo('%s %s时,凡是不懂也要装懂' %(person.type, self.type))
def GetWomanConclusion(self, person):
printInfo('%s %s时,遇事懂也装作不懂' %(person.type, self.type))
#对象结构类:遍历数据结构的操作
class ObjectStructure:
elements = []
def Attach(self, element):
self.elements.append(element)
def Detach(self, element):
self.elements.remove(element)
def Display(self, visitor):
for e in self.elements:
e.Accept(visitor)
def clientUI():
o = ObjectStructure()
o.Attach(Man())
o.Attach(Woman())
o.Display(Success())
o.Display(Failing())
o.Display(Love())
return
if __name__ == '__main__':
clientUI();
复制代码
总结
优点:
1、使得数据结构和作用于结构上的操作解耦,使得操作集合可以独立变化。
2、添加新的操作或者说访问者会非常容易。
3、将对各个元素的一组操作集中在一个访问者类当中。
4、使得类层次结构不改变的情况下,可以针对各个层次做出不同的操作,而不影响类层次结构的完整性。
5、可以跨越类层次结构,访问不同层次的元素类,做出相应的操作。
缺点:
1、增加新的元素会非常困难。
2、实现起来比较复杂,会增加系统的复杂性。
3、破坏封装,如果将访问行为放在各个元素中,则可以不暴露元素的内部结构和状态,但使用访问者模式的时候,为了让访问者能获取到所关心的信息,元素类不得不暴露出一些内部的状态和结构,就像收入和支出类必须提供访问金额和单子的项目的方法一样。
适用性:
1、数据结构稳定,作用于数据结构的操作经常变化的时候。
2、当一个数据结构中,一些元素类需要负责与其不相关的操作的时候,为了将这些操作分离出去,以减少这些元素类的职责时,可以使用访问者模式。
3、有时在对数据结构上的元素进行操作的时候,需要区分具体的类型,这时使用访问者模式可以针对不同的类型,在访问者类中定义不同的操作,从而去除掉类型判断。
扫码入群获取免费资料