公用技术——设计模式22——行为型模式——访问者模式

1、概念

  在不修改原始类结构的基础上,将原始类的某种功能委托给访问者类来实现。

  它的核心思想是”duck-typing”,忽略原始类结构,抽象其公共的功能。

  理解访问者模式的关键点,我认为有以下几点:

  1. 为什么原始类不能自己实现这种功能,一方面这个功能与类结构确实无关,例如序列化,另外一个方面这个功能有公共的步骤,例如迭代器可以被抽象为next,hasNext,这种功能通常是某些类的公共功能,如果因为实现此功能,而对所有类进行修改基本不可能。
  2. 原始类与访问者类之间的关系,如果是依赖关系,可以是构造器参数,方法返回值,方法参数,属性等等这些形式,如果是泛化关系,原始类需要实现访问者类的接口。

  例如序列化,首先原始类实现Serializable接口,而后某种其他机制实现序列化功能。

  迭代器模式只是访问者模式的一种特例,功能只有遍历功能。

  策略模式中功能是由原始类提供,而将不同的实现方式委托给其他类。访问者模式中功能和实现方式都委托给其他类,还是存在一定的差异。

  我感觉模仿Java实现迭代,比较这些功能的方式比较好,提供两个接口

  1. 第一个接口类似于Comparable,用于标识原始类是否拥有此功能。
  2. 第二个接口类似于Comparator,用于提供此功能的实现方式,不同实现类提供不同的实现方式。

2、UML图

3、代码

  没有固定的类结构,此处省略。

4、讨论

  以生活中的一个示例讨论一下,人---->交通工具。

  首先人有很多种角度,可以分为男女,可以分为父亲,母亲,儿子,女儿等等。假设系统存在很多类,它们本质都是人的抽象,但是类型却不同,例如存在User类,Employee类,Customer类,此时需要添加一种公共的功能,远行(抽象的代表从一个地方移动到另外一个地点)。

  设计Walkable(抽象的代表是否需要远行),例如Role类,它虽然是人的抽象,但是并不需要实现此接口。

  所有的这些类都实现Walkable接口,设计具体的Transfer接口,它用于抽象代表人的移动方式,可以是跑,走,可以使用交通工具,自行车,摩托车,电动车,汽车,公交车,出租车,火车,飞机,地铁等等。

  从上述理解访问者模式的两个关键问题,

  问题1:为什么原始类不能自己实现远行功能?

  答:第一原始类的基数较大,每个类都添加这个功能会很繁琐。第二这个功能与原始类的类型没有任何关系,只要它是人的抽象,便可以实现此功能。

  假设原始类是有限的,每一个都实现了此功能,例如提供了walk(Transfer transfer)方法,此时它就是策略模式,由Transfer接口提供具体的交通方式。

  问题2:原始类和委托类之间的关系?

  答:可以是依赖关系,例如构造器方法,属性,方法返回值,方法参数等等,但是更好的方式是委托类使用泛型,其中泛型T抽象的代表原始类。而用Walkable表示泛型的上限。

5、示例

  集合的排序,类的比较,类的序列化。它没有固定的格式,只要理解duck-typing这种思想即可。

原文地址:https://www.cnblogs.com/rain144576/p/9940848.html