访问者模式-Visitor(Java实现)

访问者模式-Visitor

对于某个对象或者一组对象,不同的访问者,产生的结果不同,执行操作也不同。在这种场景下就可以使用访问者模式了.

对于本文中的一组对象Archer(弓箭手)  Rider(骑兵)  Gunner(火枪手)  这一组对象, 由不同的访问者(AttackVisitor 和 RetreatVisitor)访问, 产生的结果会不同. 一种是进攻, 一种是撤退.

本例子中的类关系图如下所示:

Soldier是士兵接口. 本例子中实现了三种"士兵".

本例子中有两个visitor. 分别用来处理

加上依赖关系后如下图所示:

被作用对象

Soldier接口

public interface Soldier {
    void accept(Visitor v);
}

Archer类

public class Archer implements Soldier {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public String getArcher() {
        return "Archer";
    }
}

Gunner类

public class Gunner implements Soldier {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public String getGunner() {
        return "Gunner";
    }
}

Rider类

public class Rider implements Soldier {
    @Override
    public void accept(Visitor v) {
        v.visit(this);
    }

    public String getRider() {
        return "Rider";
    }
}

访问者

Visitor接口

public interface Visitor {
    void visit(Gunner gunner);

    void visit(Rider rider);

    void visit(Archer archer);
}

AttackVisitor类

public class AttackVisitor implements Visitor {
    @Override
    public void visit(Gunner gunner) {
        System.out.println(gunner.getGunner() + " 发起进攻");
    }

    @Override
    public void visit(Rider rider) {
        System.out.println(rider.getRider() + " 发起进攻");
    }

    @Override
    public void visit(Archer archer) {
        System.out.println(archer.getArcher() + " 发起进攻");
    }
}

RetreatVisitor类

public class RetreatVisitor implements Visitor {
    @Override
    public void visit(Gunner gunner) {
        System.out.println(gunner.getGunner() + " 开始撤退");
    }

    @Override
    public void visit(Rider rider) {
        System.out.println(rider.getRider() + " 开始撤退");
    }

    @Override
    public void visit(Archer archer) {
        System.out.println(archer.getArcher() + " 开始撤退");
    }
}

Main

运行调试

public class Main {
    public static void main(String[] args) {
        Soldier[] list = {new Gunner(), new Rider(), new Archer()};
        RetreatVisitor retreat = new RetreatVisitor();
        AttackVisitor attack = new AttackVisitor();

        for (Soldier element : list) {
            element.accept(attack);
        }

        System.out.println();

        for (Soldier element : list) {
            element.accept(retreat);
        }
    }
}

 结果如下:

 

 这段代码在github中的地址为: https://github.com/GoldArowana/design-patterns/tree/master/src/main/java/com/king/patterns/visitor

总结

在Visitor模式中, 可以很轻松地添加一个Visitor. 比如本文例子中的. 进攻有AttackVisitor, 撤退有RetreatVisitor. 

如果想再加一种Visitor呢?

比如在古代, 士兵们都是"战时打仗,闲时种地", 想再加一个FarmVisitor.

很简单啊, 只需要单独增加这个FarmVisitor就可以了, 不需要进行其他的修改. 这样就可以遍历所有的士兵, 用FarmVisitor来让所有的士兵们进行耕地了.

 

但是.如果在Visitor模式中, 想再加新的一种士兵怎么办呢?

就比如想再加一种刺客兵种 Assassin.

那可就麻烦了...现有的所有的Visitor都只支持Rider, Gunner 和 Archer. 都不支持Assassin.

所有就要给每个Visitor都新添一个方法, 让他们支持Assassin这个兵种.

 

Visitor模式的目的就是将 `处理` 从 `数据结构` 中分离出来. 如果把具体的调用写在了各个士兵类里面, 那么当扩展新功能的时候, 就需要修改这些士兵类.

而如果用了Visitor模式, 增加一个新功能, 就只需要增加一个Visitor就好了.

posted @ 2018-05-26 21:17  嗷嗷学技术  阅读(1417)  评论(0)    收藏  举报