访问者模式是指封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义于作用于这些元素的新操作。
1、要遍历不同的对象,根据对象进行不同的操作的场景; 2、当一个对象被多个不同对象顺次处理的情况,可以考虑使用访问者模式; 3、报表生成器也可以使用访问者模式实现,报表的数据源由多个不同的对象提供,每个对象都是Visitor,报表这个Element顺次Accept各访问者完善并生成对象。
class Person(object):
pass
class Man(Person):
pass
class Woman(Person):
pass
class Girl(Woman,Man):
pass
class Son(Man, Woman):
pass
class Visitor(object):
def visit(self, person, *args, **kwargs):
meth = None
#为了方便且快速地看清继承关系和顺序,可以用__mro__方法来获取这个类的调用顺序。
for cls in person.__class__.__mro__:
# print(cls)
meth_name = 'visit_'+cls.__name__
# print("----",meth_name)
# print(self)
'''
这里讲解一下:Python的hasattr(),getattr(),setattr()函数使用方法
一:hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
二:getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
三:setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。
'''
meth = getattr(self, meth_name, None)
if meth:
break
if not meth:
meth = self.generic_visit
return meth(person, *args, **kwargs)
#普通访问入口
def generic_visit(self, person, *args, **kwargs):
# 这里可以写处理逻辑
print('generic_visit '+person.__class__.__name__)
#妇女访问入口
def visit_Woman(self, person, *args, **kwargs):
# 这里可以写处理逻辑
print('visit_Woman '+person.__class__.__name__)
#男人访问入口
def visit_Man(self, person, *args, **kwargs):
# 这里可以写处理逻辑
print('visit_Man '+person.__class__.__name__)
if __name__ == '__main__':
p=Person()
man = Man()
woman = Woman()
girl = Girl()
son = Son()
visitor = Visitor()
visitor.visit(p)
visitor.visit(man)
visitor.visit(son)
visitor.visit(woman)
visitor.visit(girl)
输出结果如下:
generic_visit Person
visit_Man Man
visit_Man Son
visit_Woman Woman
visit_Woman Girl
备注
class Man(Person)--->这里会在类的继承关系中会指定调用visit_Man方法
class Son(Man,Woman)--->这里会在类的继承关系中优先找到并调用visit_Man方法
class Woman(Person)--->这里会在类的继承关系中会指定调用visit_Woman方法
class Girl(Woman,Man)--->这里会在类的继承关系中优先找到并调用visit_Woman方法
找到了对应的方法就可以执行对应的业务逻辑。
1、将不同的职责非常明确地分离开来,符合单一职责原则; 2、职责的分开也直接导致扩展非常优良,灵活性非常高,加减元素和访问者都非常容易。
end