《设计模式》-- 访问者模式

访问者模式

参考:《JAVA与模式》之访问者模式

认识

访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。变化的是访问者,不变的是被访问者

思考

本质是:预留通路,回调实现

有条件的接收访问,如果不满足条件,禁止访问

使用场景

  • 对象结构很少变动,对对象的操作经常改变的时候可以封装操作使用访问者模式
  • 对对象结构中的各个元素有不同的操作时,可以给各个元素封装不同的操作使用访问者模式

优缺点

  • 优点

    1. 好的扩展性:能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
    2. 好的复用性:可以通过访问者来定义整个对象结构通用的功能,从而提高复用程度。
    3. 分离无关行为:可以通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
  • 缺点

    1. 对象结构变化很困难:对象结构发生了改变,访问者的接口和访问者的实现都要发生相应的改变,代价太高
    2. 破坏封装:访问者模式通常需要对象结构开放内部数据给访问者和ObjectStructrue,这破坏了对象的封装性。

UML图

数据结构的每一个节点都可以接受一个访问者的调用,然后节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做“双重分派”。节点调用访问者,将它自己传入,访问者通过传入的节点对象执行节点的相关操作 。访问者模式的示意性类图如下所示:

image

  • 抽象访问者(Visitor)角色:声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。
  • 具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
  • 抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数
  • 具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
  • 结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如List或Set。

执行顺序图

image

代码实现

//访问者接口,为每个节点实体重载提供了接口
public interface Visitor {
    //对应于NodeA的访问操作
    public void visit(NodeA node);
    //对应于NodeB的访问操作
    public void visit(NodeB node);
}

//具体访问者
public class VisitorA implements Visitor {
    //对应于NodeA的访问操作
    @Override
    public void visit(NodeA node) {
        System.out.println(node.operationA());
    }
    //对应于NodeB的访问操作
    @Override
    public void visit(NodeB node) {
        System.out.println(node.operationB());
    }
}
//具体访问者
public class VisitorB implements Visitor {
    //对应于NodeA的访问操作
    @Override
    public void visit(NodeA node) {
        System.out.println(node.operationA());
    }
    //对应于NodeB的访问操作
    @Override
    public void visit(NodeB node) {
        System.out.println(node.operationB());
    }
}
//抽象节点
public abstract class Node {
    //接受操作
    public abstract void accept(Visitor visitor);
}
//具体节点类NodeA
public class NodeA extends Node{
    //接受访问者
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    //NodeA特有的方法
    public String operationA(){
        return "NodeA";
    }
}
//具体节点类NodeB
public class NodeB extends Node{
   //接受访问者
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    // NodeB特有的方法
    public String operationB(){
        return "NodeB";
    }
}
//结构对象角色类,这个结构对象角色持有一个聚集,并向外界提供add()方法作为对聚集的管理操作。通过调用这个方法,可以动态地增加一个新的节点。
public class ObjectStructure {
    //聚合节点
    private List<Node> nodes = new ArrayList<Node>();

    // 循环访问多个节点
    public void action(Visitor visitor){

        for(Node node : nodes)
        {
            node.accept(visitor);
        }

    }
    // 添加一个新节点元素
    public void add(Node node){
        nodes.add(node);
    }
}
//客户端
public class Client {

    public static void main(String[] args) {
        //创建一个结构对象
        ObjectStructure os = new ObjectStructure();
        //给结构增加一个节点
        os.add(new NodeA());
        //给结构增加一个节点
        os.add(new NodeB());
        //创建一个访问者
        Visitor visitor = new VisitorA();
        os.action(visitor);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值