设计模式——访问者模式
更多内容,前往 IT-BLOG
在开发中,有些集合存在多种不同的对象实例(例如:男人、女人),且每个对象也存在多种不同的访问者或处理方式(性格:暴躁、温和)。这样的例子还有很多,例如:好声音节目中不同评委,以及评委对他们的评价的选项,等等。这些被处理的数据元素相对稳定,而访问方式多种多样的数据结构,如果使用 “访问者模式” 来处理比较方便。访问者模式能把处理方法从数据结构中分离出来,并可以根据需要增加新的处理方式,且不用修改原来的程序代码与数据结构,这提高了代码的扩展性和灵活性。
一、访问者模式基本介绍
【1】访问者模式(Visitor Pattern):封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
【2】主要将数据结构与数据操作分离:解决数据结构和操作耦合性问题。
【3】访问者模式的基本工作原理:在被访问者(上面提到的评委)的类里面加一个对外提供接待访问者的接口。
【4】访问者模式主要应用场景:需要对一个对象结构中的对象进行很多不同的操作(这些操作彼此没有关联),同时避免让这些操作 “污染” 这些类对象,可以选用访问者模式。
二、访问者模式的优缺点
【访问者(Visitor)模式,其主要优点如下】:
● 扩展性好:能够在不修改对象结构中元素的情况下,为对象结构中的元素添加新功能;
● 复用性好:可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用功能;
● 灵活性好:访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由;
【访问者(Visitor)模式,其主要缺点如下】:
● 增加新的元素类很困难:在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加响应的具体操作,违背了 “开闭原则”。
● 破坏封装:访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
● 违反了依赖倒置原则:访问模式依赖了具体类,而没有依赖抽象类。
● 具体元素对访问者公布细节:也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的,这样造成了具体元素变得更比较困难。
三、访问者模式结构类图
访问者模式的关键在于:如何将元素的操作分离出来封装成独立的类,其基本机构如下:
【1】抽象访问者角色(Visitor):定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作,该操作中的参数类型标识了被访问的具体元素。
【2】具体访问者角色(ConcreteVisitor):实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
【3】抽象元素角色(Element):声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept 方法的参数。
【4】具体元素角色(ConcreteElement):实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this),另外具体元素中可能包含本身业务逻辑的相关操作。
【5】对象结构角色(Object Structure):是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由List、Set、Map 等聚合类实现。
四、访问者模式案例分析
评委评价歌手是否晋级的案例
【1】抽象访问者角色
【2】抽象访问者的具体实现类——晋级
【3】抽象访问者的具体实现类——淘汰
当需要扩展一个 “待定” 的元素选项时,非常方便,简单两步操作即可完成:
【1】添加 “待定” 元素的实体类,如下:并实现所有评委给的 “待定评价” 即可。