访问者模式,很多人认为是最难的一种设计模式。我觉得是名字没起好。我们先换个名字,不如叫它读者模式,我们知道一千个读者有一千个哈姆雷特。也就是说同一个对象,不同的读者会有不同的操作。代码如下:
public class Visitor {
abstract static class Element {//抽象的书
public abstract void accept(IVisitor visitor);
public abstract void doSomething();
}
interface IVisitor {//我们的读者接口
void visit(ConcreteElement1 el1);
void visit(ConcreteElement2 el2);
// void visit(Element el2);//为了区分不同子类,没用这种形式。不需区分时推荐这种,增加子类更简单
}
static class ConcreteElement1 extends Element {
public void doSomething() {
System.out.println("哈姆雷特");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
static class ConcreteElement2 extends Element {
public void doSomething() {
System.out.println("红楼梦");
}
public void accept(IVisitor visitor) {
visitor.visit(this);
}
}
static class Vistor1 implements IVisitor {//第一个读者只看了书名
public void visit(ConcreteElement1 el1) {
el1.doSomething();
}
public void visit(ConcreteElement2 el2) {
el2.doSomething();
}
}
static class Vistor2 implements IVisitor {//第二个读者读完后
public void visit(ConcreteElement1 el1) {
System.out.print("很伤心:");
el1.doSomething();
}
public void visit(ConcreteElement2 el2) {
System.out.print("特别伤心:");
el2.doSomething();
}
}
public static void main(String[] args) {
List<Element> list = new ArrayList<>();
list.add(new ConcreteElement1());
list.add(new ConcreteElement2());
for (Element e : list) {//普通方式
e.doSomething();
}
for (Element e : list) {//访问者模式,为啥要搞这么复杂传个Vistor1,结果还是调用自己呢,看下面
e.accept(new Vistor1());
}
for (Element e : list) {//访问者模式做扩展,只需要加个Vistor2
e.accept(new Vistor2());
}
}
}
输出:
哈姆雷特
红楼梦
哈姆雷特
红楼梦
很伤心:哈姆雷特
特别伤心:红楼梦
现在应该明白了吧,说到底就是为了对同一对象做不同操作。也没说的那么难是吧,注释掉的那句可以好好研究下。
觉得容易理解的话面向对象的23种设计模式点这里