设计模式-访问者模式

2019-10-09 00:21发布

什么是访问者模式

什么叫做访问,如果大家学过数据结构,对于这点就很清晰了,遍历就是访问的一般形式,单独读取一个元素进行相应的处理也叫作访问,读取到想要查看的内容+对其进行处理就叫做访问,那么我们平常是怎么访问的,基本上就是直接拿着需要访问的地址(引用)来读写内存就可以了。

最复杂的设计模式,并且使用频率不高,《设计模式》的作者评价为:大多情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就真的需要使用了。

访问者模式是一种将数据操作和数据结构分离的设计模式。(觉得太抽象,可以看下面的例子)。

访问者模式解决了什么问题

为什么还要有一个访问者模式呢,这就要放到OOP之中了,在面向对象编程的思想中,我们使用类来组织属性,以及对属性的操作,那么我们理所当然的将访问操作放到了类的内部,这样看起来没问题,但是当我们想要使用另一种遍历方式要怎么办呢,我们必须将这个类进行修改,这在设计模式中是大忌,在设计模式中就要保证,对扩展开放,对修改关闭的开闭原则。

访问者模式的使用场景

  1. 对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

访问者模式的UML类图


访问者模式

角色描述

  • Visitor:接口或者抽象类,定义了对每个 Element 访问的行为,它的参数就是被访问的元素,它的方法个数理论上与元素的个数是一样的,因此,访问者模式要求元素的类型要稳定,如果经常添加、移除元素类,必然会导致频繁地修改 Visitor 接口,如果出现这种情况,则说明不适合使用访问者模式。
  • ConcreteVisitor:具体的访问者,它需要给出对每一个元素类访问时所产生的具体行为。
  • Element:元素接口或者抽象类,它定义了一个接受访问者(accept)的方法,其意义是指每一个元素都要可以被访问者访问。
  • ElementA、ElementB:具体的元素类,它提供接受访问的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
  • ObjectStructure:定义当中所提到的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素提供访问者访问。

如何使用访问者模式

调用

package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
Host host = new HostManager();
host.accept(new VisitorOne());
}
}

访问者接口

package com.company;
public interface Visitor {
void visit(HostManager manager);
void visit(HostOne one);
void visit(HostTwo two);
void visit(HostThree three);
}

访问者

package com.company;
public class VisitorOne implements Visitor {
@Override
public void visit(HostManager manager) {
System.out.println("现在访问的是管家");
}
@Override
public void visit(HostOne one) {
System.out.println("现在访问的是Host1");
}
@Override
public void visit(HostTwo two) {
System.out.println("现在访问的是Host2");
}
@Override
public void visit(HostThree three) {
System.out.println("现在访问的是Host3");
}
}





东道主接口
package com.company;
public interface Host {
void accept(Visitor visitor);
}
东道主管家
package com.company;
public class HostManager implements Host {
private Host hosts[];
public HostManager() {
this.hosts = new Host[]{new HostOne(),new HostTwo(),new HostThree()};
}
@Override
public void accept(Visitor visitor) {
for (int index = 0;index < this.hosts.length;index++) {
this.hosts[index].accept(visitor);
}
visitor.visit(this);
}
}

东道主1

package com.company;
public class HostOne implements Host {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

东道主2

package com.company;
public class HostTwo implements Host {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}

东道主3

package com.company;
public class HostThree implements Host {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
文章来源: https://www.toutiao.com/group/6738172783634678283/