文章目录
终于到了最后一个模式了,整理完访问者模式,23种设计模式就全部过了一遍了。完成时间比预期的晚了几天,但是也相差不大了,主要是时间太紧了。
访问者模式往年考过简答题,细细的整理一下。感觉这个模式结构还是挺复杂的。
访问者模式
定义:
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
结构:
抽象访问者(visitor):定义了对每一个元素访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素个数是一样的,即访问者模式要求元素类的个数不能变。
具体访问者(concretevisitor):给出对每一个元素类访问时所产生的具体行为。
抽象元素(element):定义了一个接受访问者的方法(accept),其意义是指,每一个元素都要可以被访问者访问。
具体元素(concreteElement):提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
对象结构(objectstructure):定义当中所提到的对象结构,对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它含有一组元素(element),并且可以迭代这些元素,供访问者访问。
场景分析:
针对一个保存有不同类型对象的聚集采取某种操作,而操作细节根据元素类型不同而不同,就会出现对元素类型做判断的条件转移语句。
解决方案:访问者模式
双重分派很重要!!!!!!
双重分派:数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者则反过来执行节点对象的操作。
提供了倾斜的可扩展性设计。
优点:
增加新操作容易,将有关行为集中到一个访问者对象,把所有对象管理放在一个接口中。
扩展性好,在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
复用性好,通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
分离无关行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
缺点:
增加新的节点类变得很困难。每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了开闭原则。
访问者模式依赖了具体类,而没有依赖抽象类。
本质:
预留通路,回调实现。
理解:
访问者模式适用于数据结构相对稳定的系统。它把数据结构(元素)和作用于结构上的操作(访问者)之间的耦合解脱开,使得操作集合可以相对自由的演化。
访问者模式的目的是要把处理从数据结构分离出来。
如果有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较适合的,因为访问者模式使得算法操作的增加变得容易。访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。缺点就就是使得增加新的数据结构变得困难了。
使用场景:
对象结构相对稳定,但其操作算法经常变化的程序。
对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
package 访问者模式;
public abstract class Element {
public abstract void Accept(Visitor visitor);
}
package 访问者模式;
public class ConcreteElementA extends Element {
@Override
public void Accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
}
package 访问者模式;
public class ConcreteElementB extends Element {
@Override
public void Accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
}
package 访问者模式;
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
package 访问者模式;
public class ConcreteVisitorA extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA + "被ConcreteVisitorA访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB + "被ConcreteVisitorA访问");
}
}
package 访问者模式;
public class ConcreteVisitorB extends Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println(concreteElementA + "被ConcreteVisitorB访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println(concreteElementB + "被ConcreteVisitorB访问");
}
}
package 访问者模式;
import java.util.ArrayList;
import java.util.List;
public class ObjectStructure {
private List<Element> elements = new ArrayList<Element>();
public void attach(Element element) {
elements.add(element);
}
public void detch(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for (int i = 0; i < elements.size(); i++) {
Element e = elements.get(i);
e.Accept(visitor);
}
}
}
package 访问者模式;
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new ConcreteElementA());
objectStructure.attach(new ConcreteElementB());
ConcreteVisitorA v1 = new ConcreteVisitorA();
ConcreteVisitorB v2 = new ConcreteVisitorB();
objectStructure.accept(v1);
objectStructure.accept(v2);
}
}