在软件设计中,经常会遇到对系统中一个已经完成设计与代码编写的类的层次结构进行功能修改或增加新功能的情况,这就需要对该层次结构的某些类进行修改。如果改动量较小尚可,但是往往这种变动会经常发生,且任何变动都可能导致整个类层次结构中的大多数类都随之进行修改。此时,最好考虑对这个层次类重构。即将介绍的访问者模式(Visitor Pattern)可以用来解决类似的问题。访问者模式在处理数据结构较稳定,但是作用于其上的操作需要经常变化的问题时是非常有效的。
访问者模式是指作用于一个对象结构体上的元素的操作。访问者可以使用户在不改变该结构体中的类的基础上定义一个新的操作。
访问者模式的类图如图所示。
该类图包含两个系列的类:一个是 Element 类,另外一个是访问者类。访问者类定义了施加于 Element 类上的操作,为 Element 类提供一些功能。可以有多种具体的访问者类,各自完成特定的目的,如一个访问者类是计算价格,另一个访问者类则是计算存货数量。因此需要定义一个抽象的访问者父类 Visitor 以及用于各种特殊目的具体的子类。Visitor 类必须给每个结点类提供一个操作,即访问方法,例如获得各结点所代表的商品对象的价格等。
访问者模式的各组成部分及说明如下。
在以下情况可以使用访问者模式。
访问者模式的优点如下。
访问者模式的缺点是,增加一个具体的新 ConcreteElement 类比较困难。因为此时需要在每一个 ConcreteVisitor 类中添加该 ConcreteElement 类的访问方法。
from abc import ABC, abstractmethod
class Visitor(ABC):
@abstractmethod
def visit_element_a(self, element_a):
pass
@abstractmethod
def visit_element_b(self, element_b):
pass
class ConcreteVisitor1(Visitor):
def visit_element_a(self, element_a):
print('ConcreteVisitor1', 'element_a')
def visit_element_b(self, element_b):
print('ConcreteVisitor1', 'element_b')
class ConcreteVisitor2(Visitor):
def visit_element_a(self, element_a):
print('ConcreteVisitor2', 'element_a')
def visit_element_b(self, element_b):
print('ConcreteVisitor2', 'element_b')
class Element(ABC):
@abstractmethod
def accept(self, visitor):
pass
class ElementA(Element):
def accept(self, visitor):
visitor.visit_element_a(self)
class ElementB(Element):
def accept(self, visitor):
visitor.visit_element_b(self)
class ObjectStructure:
def __init__(self):
self.elements = [ElementA(), ElementB()]
class Client:
@staticmethod
def main():
object_structure = ObjectStructure()
visitor = ConcreteVisitor1()
for element in object_structure.elements:
element.accept(visitor)
visitor = ConcreteVisitor2()
for element in object_structure.elements:
element.accept(visitor)
if __name__ == '__main__':
Client.main()
本文分享自 Python机器学习算法说书人 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!