zoukankan      html  css  js  c++  java
  • 行为类型11-4:访问者模式(Visitor Pattern)

    1. 概述

    在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

    表示一个作用于某对象结构中的各元素的操作。
    它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

    2. 介绍

    2.1 意图

    主要将数据结构与数据操作分离。

    2.2 主要解决

    稳定的数据结构和易变的操作耦合问题。

    2.3 何时使用

    需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

    2.4 如何解决

    在被访问的类里面加一个对外提供接待访问者的接口。

    2.5 关键代码

    在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

    2.6 应用实例

    您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

    2.7 优点

    1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

    2.8 缺点

    1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

    2.9 使用场景

    1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

    2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

    3、一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。

    2.10 注意事项

    访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

    3. 参与者

    1.Visitor
    	为该对象结构中ConcreteElement的每一个类声明一个Visit操作。
    	该操作的名字和特征标识了发送Visit请求给该访问者的那个类。
    	这使得访问者可以确定正被访问元素的具体的类。
    	这样访问者就可以通过该元素的特定接口直接访问它。
    
    2.ConcreteVisitor
    	实现每个由Visitor声明的操作。
    	每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。
    	ConcreteVisitor为该算法提供了上下文并存储它的局部状态。
    	这一状态常常在遍历该结构的过程中累积结果。
    
    3.Element
    	定义一个Accept操作,它以一个访问者为参数。
    
    4.ConcreteElement
    	实现Accept操作,该操作以一个访问者为参数。
    
    5.ObjectStructure
    	能枚举它的元素。
    	可以提供一个高层的接口以允许该访问者访问它的元素。
    	可以是一个复合或是一个集合,如一个列表或一个无序集合。
    

    4. 类图

    在这里插入图片描述

    5. 例子

    5.1 Visitor

    public interface Visitor {
        public void visitString(StringElement stringE);
        public void visitFloat(FloatElement floatE);
        public void visitCollection(Collection collection); 
    }
    

    5.2 ConcreteVisitor

    public class ConcreteVisitor implements Visitor {
    
        public void visitCollection(Collection collection) {
            // TODO Auto-generated method stub
            Iterator iterator = collection.iterator();
            while (iterator.hasNext()) {
                Object o = iterator.next();
                if (o instanceof Visitable) {
                    ((Visitable)o).accept(this);
                }
            }
        }
    
        public void visitFloat(FloatElement floatE) {
            System.out.println(floatE.getFe());
        }
    
        public void visitString(StringElement stringE) {
            System.out.println(stringE.getSe());
        }
    }
    

    5.3 Element

    public interface Visitable {
        public void accept(Visitor visitor);
    }
    

    5.4 ConcreteElement

    public class FloatElement implements Visitable {
        private Float fe;
        
        public FloatElement(Float fe) {
            this.fe = fe;
        }
        
        public Float getFe() {
            return this.fe;
        }
        
        public void accept(Visitor visitor) {
            visitor.visitFloat(this);
        }
    }
    
    public class StringElement implements Visitable {
        private String se;
        
        public StringElement(String se) {
            this.se = se;
        }
        
        public String getSe() {
            return this.se;
        }
        
        public void accept(Visitor visitor) {
            visitor.visitString(this);
        }
    }
    

    Test

    public class Test {
    
        public static void main(String[] args) {
            Visitor visitor = new ConcreteVisitor();
            StringElement se = new StringElement("abc");
            se.accept(visitor);
            
            FloatElement fe = new FloatElement(new Float(1.5));
            fe.accept(visitor);
            System.out.println("===========");
            List result = new ArrayList();
            result.add(new StringElement("abc"));
            result.add(new StringElement("abc"));
            result.add(new StringElement("abc"));
            result.add(new FloatElement(new Float(1.5)));
            result.add(new FloatElement(new Float(1.5)));
            result.add(new FloatElement(new Float(1.5)));
            visitor.visitCollection(result);
        }
    }
    

    result

    abc
    1.5
    ===========
    abc
    abc
    abc
    1.5
    1.5
    1.5
    

    6. 示例2

    我们将创建一个定义接受操作的 ComputerPart 接口。KeyboardMouseMonitorComputer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。

    VisitorPatternDemo,我们的演示类使用 ComputerComputerPartVisitor 类来演示访问者模式的用法。
    在这里插入图片描述

    6.1

    public interface ComputerPart {
        public void accept(ComputerPartVisitor computerPartVisitor);
    }
    
    class Keyboard  implements ComputerPart {
    
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            computerPartVisitor.visit(this);
        }
    }
    
    class Monitor implements ComputerPart{
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            computerPartVisitor.visit(this);
        }
    }
    
    class Mouse implements ComputerPart{
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            computerPartVisitor.visit(this);
        }
    }
    
    class Computer implements ComputerPart{
        ComputerPart[] parts;
    
        public Computer() {
            parts = new ComputerPart[]{
                    new Mouse(),
                    new Keyboard(),
                    new Monitor()
            };
        }
    
        @Override
        public void accept(ComputerPartVisitor computerPartVisitor) {
            for (int i = 0; i < parts.length; i++) {
                parts[i].accept(computerPartVisitor);
            }
            computerPartVisitor.visit(this);
        }
    }
    
    public interface ComputerPartVisitor {
        public void visit(Computer computer);
        public void visit(Mouse mouse);
        public void visit(Keyboard keyboard);
        public void visit(Monitor monitor);
    }
    
    class ComputerPartDisplayVisitor implements ComputerPartVisitor{
        @Override
        public void visit(Computer computer) {
            System.out.println("Displaying Computer.");
        }
    
        @Override
        public void visit(Mouse mouse) {
            System.out.println("Displaying Mouse.");
        }
    
        @Override
        public void visit(Keyboard keyboard) {
            System.out.println("Displaying Keyboard.");
        }
    
        @Override
        public void visit(Monitor monitor) {
            System.out.println("Displaying Monitor.");
        }
    }
    

    test

    public class VisitorPatternDemo {
        public static void main(String[] args) {
            ComputerPart computerPart = new Computer();
            computerPart.accept(new ComputerPartDisplayVisitor());
        }
    }
    

    result

    Displaying Mouse.
    Displaying Keyboard.
    Displaying Monitor.
    Displaying Computer.
    
  • 相关阅读:
    TCP和UDP知识总结
    使用 DataX 增量同步数据(转)
    python对象类型
    Asp.net mvc使用SignaIR
    数据库分库分表思路 [转]
    Linux基本操作 [转]
    RabbitMQ入门教程 [转]
    设计模式
    设计模式六大原则
    Javascript实现数组去重 [转]
  • 原文地址:https://www.cnblogs.com/daozhangblog/p/12446360.html
Copyright © 2011-2022 走看看