Java设计模式(23)——行为模式之访问者模式(Visitor)

摘要:
它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作。

一、概述

概念

Java设计模式(23)——行为模式之访问者模式(Visitor)第1张

作用于某个对象群中各个对象的操作。它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作。

引入

试想这样一个场景,在一个Collection中放入了一大堆的各种对象的引用,取出时却需要根据这些对象的不同具体类型执行不同操作,那我们有如下方案:

public voidshow(Collection c) {
        Iterator it =c.iterator();
        while(it.hasNext()) {
            Object o =it.next();
            if (o instanceofInteger) {
                //Integer对应的操作
            } else if (o instanceofString) {
                //String对应的操作
            } else if (o instanceofCollection) {
                //Collection对应的操作
            } else{
                //省略若干个else if
} 
        }
    }

就不分析说这段代码到底有什么问题了,我们直接引入解决办法:访问者模式——把数据结构和数据结构之上的操作解耦

UML简图

Java设计模式(23)——行为模式之访问者模式(Visitor)第2张

结构

Java设计模式(23)——行为模式之访问者模式(Visitor)第3张

角色

抽象访问者:声明多个访问操作

具体访问者:实现接口中操作

抽象节点:声明接受操作,接收访问者作为一个参量

具体节点:实现接受操作

结构对象:可以遍历结构中所有元素

二、实践

根据角色给出示意性代码:

抽象访问者

/**
 * 访问者接口
 *
 * @authorAdministrator
 **/
public interfaceVisitor {
    /**
     * 访问NodeA
     * @paramnode 访问结点
     */
    voidvisit(NodeA node);
    /**
     * 访问NodeB
     * @paramnode 访问结点
     */
    voidvisit(NodeB node);
}

具体访问者

/**
 * 访问者A
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class VisitorA implementsVisitor{
    @Override
    public voidvisit(NodeA nodeA) {
        System.out.println(nodeA.operationA());
    }
    @Override
    public voidvisit(NodeB nodeB) {
        System.out.println(nodeB.operationB());
    }
}
/**
 * 访问者B
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class VisitorB implementsVisitor{
    @Override
    public voidvisit(NodeA nodeA) {
        System.out.println(nodeA.operationA());
    }
    @Override
    public voidvisit(NodeB nodeB) {
        System.out.println(nodeB.operationB());
    }
}

抽象结点

/**
 * 抽象节点
 *
 * @authorAdministrator ON 2017/11/3
 **/
public abstract classNode {
    public abstract voidaccept(Visitor v);
}

具体结点

/**
 * A结点
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class NodeA extendsNode{
    @Override
    public voidaccept(Visitor v) {
        v.visit(this);
    }
    publicString operationA() {
        return "A结点特有方法";
    }
}
/**
 * B结点
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class NodeB extendsNode{
    @Override
    public voidaccept(Visitor v) {
        v.visit(this);
    }
    publicString operationB() {
        return "B结点特有方法";
    }
}

结构对象

/**
 * 结构对象
 *
 * @authorAdministrator ON 2017/11/3
 **/
public classObjectStructure {
    private List<Node>nodeList;
    privateNode node;
    publicObjectStructure() {
        nodeList = new ArrayList<>();
    }
    /**
     * 执行访问操作
     */
    public voidaction(Visitor v) {
        Iterator<Node> iterator =nodeList.iterator();
        while(iterator.hasNext()) {
            node =iterator.next();
            node.accept(v);
        }
    }
    /**
     * 增加一个新结点
     * @paramnode 待增加的结点
     */
    public voidadd(Node node) {
        nodeList.add(node);
    }
}

客户端简单操作:

public static voidmain(String[] args) {
        //新建并初始化结构对象
        ObjectStructure os = newObjectStructure();
        os.add(newNodeA());
        os.add(newNodeB());
        //新增访问者并访问
        Visitor v1 = newVisitorA();
        os.action(v1);
    }

Java设计模式(23)——行为模式之访问者模式(Visitor)第4张

我们根据访问者的核心,把上面提出的问题使用访问者模式进行改进

访问者接口——通过重载实现了不同类型的不同访问

/**
 * 集合访问者接口
 *
 * @authorAdministrator
 **/
public interfaceCollectionVisitor {
    /**
     * 访问String元素
     * @paramse String类型元素
     */
    voidvisit(StringElement se);
    /**
     * 访问Integer类型元素
     * @paramie Integer类型元素
     */
    voidvisit(IntegerElement ie);
}

具体访问者

/**
 * 具体访问者
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class ConcreteVisitor implementsCollectionVisitor{
    @Override
    public voidvisit(StringElement se) {
        System.out.println(se.stringValue());
    }
    @Override
    public voidvisit(IntegerElement ie) {
        System.out.println(ie.integerValue());
    }
}

抽象被访问元素——通过accept接收访问者

/**
 * 元素接口
 *
 * @authorAdministrator ON 2017/11/3
 **/
public interfaceElement {
    /**
     * 接收访问
     * @paramvisitor 访问者
     */
    voidaccept(CollectionVisitor visitor);
}

具体元素

/**
 * String类型的元素
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class StringElement implementsElement{
    @Override
    public voidaccept(CollectionVisitor visitor) {
        visitor.visit(this);
    }
    publicString stringValue() {
        return "StringElement";
    }
}
/**
 * Integer类型元素
 *
 * @authorAdministrator ON 2017/11/3
 **/
public class IntegerElement implementsElement{
    @Override
    public voidaccept(CollectionVisitor visitor) {
        visitor.visit(this);
    }
    publicInteger integerValue() {
        return 1;
    }
}

客户端使用

/**
 * 客户端
 * @authorAdministrator
 **/
public classClient {
    public static voidmain(String[] args) {
        //创建需要访问的元素对象集合
        List<Element> elementList = new ArrayList<>();
        elementList.add(newStringElement());
        elementList.add(newIntegerElement());
        //创建访问者
        CollectionVisitor visitor = newConcreteVisitor();
        //接收访问者开始访问
        for(Element element : elementList) {
            element.accept(visitor);
        }
    }
}

三、改进与思考

应当指明,只有在系统十分稳定,确定不会加入新结点时使用,因为加入新节点将无法做到“开闭原则”

特别注意,访问者模式是解决了不停判断的问题!可以直接根据传入的参数进行判断和接收(回传球)

浅显的栗子请参见:http://ifeve.com/visitor-design-pattern-in-java-example-tutorial/

免责声明:文章转载自《Java设计模式(23)——行为模式之访问者模式(Visitor)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇图书管理系统【用户、购买、订单模块、添加权限】XRender 扩展的设计和实现(Design and Implementation of the X Rendering Extension)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java中的23种设计模式之——访问者(Visitor)模式(7)

1、访问者(Visitor)模式:表示一个作用于某对象结构中的各元素的操作,它使你在不改变各元素的类的前提下定义作用于这些元素的新操作。 类图: 访问者模式结构:访问者角色(Visitor): 为该对象结构中具体元素角色声明一个访问操作接口.具体访问者角色(Concrete Visitor): 实现每个由访问者角色(Visitor)声明的操作.元素角色(...

C#设计模式-访问者模式

一、 访问者(Vistor)模式 访问者模式是封装一些施加于某种数据结构之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变。访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变。 数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象...

Java开发中的23种设计模式详解(转)

设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如...