访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作。
它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
具体的意思就是,你有好几个对象(建议不能轻易增加或删除),然后
还有好几个基于这几种不同种类对象的操作。
这时,就可以把操作和类分开,进而当增加一个新的操作时,并不用动
原有的数据结构对象,而仅仅添加一个新类即可。
所以说,访问者模式吧数据结构和租用于数据结构上的操作之间的耦合解脱开,
使得操作集合可以相对自由的演化。
接下来看看类图:
由上面类图:
元素类Element就代表着普通的数据结构,即对象。
而Visitor类则代表相应的操作。
这样的情况下,试想,如果你想再增加一个操作,所做的仅仅是新创建一个类,
然后继承自Visitor,添加相关业务代码就可以了。而不用修改Element中的代码。
但是也有另外一个缺点,就是如果你要新增加一个Element类,那需要改动的地方就很多了,
几乎包括整个Visitor继承体系。
下面看看类代码:
Element类:
package com.blog.anla.Visitor;
/**
* 元素的抽象父类,
* 一般的情况下,当使用访问者模式时,
* 要求他的子类是基本固定的,不要随意更改的。
* @author U-ANLA
*
*/
public abstract class Element {
public abstract void accept(Visitor visitor);
}
ConcreteElementA类:
package com.blog.anla.Visitor;
/**
* 具体元素1,作为element子元素,建议不要轻易添加或者删除。
* 实现处理元素与数据分离
* @author U-ANLA
*
*/
public class ConcreteElementA extends Element{
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void otherMethodA(){}
}
ConcreteElementB类:
package com.blog.anla.Visitor;
/**
* 具体元素2,作为element子元素,建议不要轻易添加或者删除。
* @author U-ANLA
*
*/
public class ConcreteElementB extends Element{
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
public void otherMethodB(){}
}
Visitor类:
package com.blog.anla.Visitor;
/**
* 为该对象结构中每一个ConcreteElemetn都声明一个
* visit操作,如下面的visitA和visitB
* 如果element元素更改的话,就会直接导致这里面要改,
* 以及visitor的子类也要改,所以适合element元素基本不该动
* 的系统中使用
* @author U-ANLA
*
*/
public abstract class Visitor {
public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);
}
ConcreteVisitor1类:
package com.blog.anla.Visitor;
/**
* 具体访问者1,或者可以理解成为某一种状态的改变
* 即element状态的改变。
* @author U-ANLA
*
*/
public class ConcreteVisitor1 extends Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println("concreteElemtnA 被 ConcreteVisitor1访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println("concreteElemtnB 被 ConcreteVisitor1访问");
}
}
ConcreteVisitor2类:
package com.blog.anla.Visitor;
public class ConcreteVisitor2 extends Visitor{
@Override
public void visitConcreteElementA(ConcreteElementA concreteElementA) {
System.out.println("concreteElemtnA 被 ConcreteVisitor2访问");
}
@Override
public void visitConcreteElementB(ConcreteElementB concreteElementB) {
System.out.println("concreteElemtnB 被 ConcreteVisitor2访问");
}
}
ObjectStructure类:
package com.blog.anla.Visitor;
import java.util.ArrayList;
import java.util.List;
/**
* 能枚举它的元素,可以提供一个高层接口以允许访问者访问
* 它的元素。
* @author U-ANLA
*
*/
public class ObjectStructure {
private List<Element> elements = new ArrayList<Element>();
public void attach(Element element){
elements.add(element);
}
public void detach(Element element){
elements.remove(element);
}
public void accept(Visitor visitor){
for(int i = 0;i < elements.size();i++){
elements.get(i).accept(visitor);
}
}
}
根据代码结合类图理解会更到位哦
赠人玫瑰手留余香(oo)
设计模式相关代码以及类图的整个项目都托管到了github上,包括各个模式的示例
代码以及类图,类图则用的visio绘制,整个visio文件也在该项目上,这里贴上地址:
https://github.com/anLA7856/design
如果觉得有帮助,start一下呗~我会非常开心的