訪问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式。

据《大话设计模式》中说算是最复杂也是最难以理解的一种模式了。

   定义(源于GoF《Design Pattern》):表示一个作用于某对象结构中的各元素的操作。它使你能够在
不改变各元素类的前提下定义作用于这些元素的新操作。从定义能够看出结构对象是使用訪问者模式必备
条件,并且这个结构对象必须存在遍历自身各个对象的方法。这便类似于Java语言其中的collection概念了。
  涉及角色 :
  1.IVisitor 抽象訪问者角色,为该对象结构中详细元素角色声明一个訪问操作接口。该操作接口的名字和
參数标识了发送訪问请求给具休訪问者的具休元素角色,这样訪问者就能够通过该元素角色的特定接口直接訪问它。

  2.ConcreteVisitor.详细訪问者角色,实现Visitor声明的接口。
  3.Element 定义一个接受訪问操作(accept()),它以一个訪问者(Visitor)作为參数。
  4.ConcreteElement 详细元素,实现了抽象元素(Element)所定义的接受操作接口。

  5.ObjectStructure 结构对象角色,这是使用訪问者模式必备的角色。

它具备下面特性:

能枚举它的元素;能够提供一个高层接口以同意訪问者訪问它的元素;如有须要,能够设计成一个
复合对象或者一个聚集(如一个列表或无序集合)。

  訪问者模式的几个特点:
  訪问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
  訪问者模式适用于数据结构相对稳定算法又易变化的系统。

由于訪问者模式使得算法操作添加变得easy。

若系统数据结构对象易于变化。常常有新的数据对象添加进来,则不适合使用訪问者模式。
  訪问者模式的长处是添加操作非常easy,由于添加操作意味着添加新的訪问者。

訪问者模式将有关行为集中

到一个訪问者对象中,其改变不影响系统数据结构。其缺点就是添加新的数据结构非常困难。
  适用情况 :
  1) 一个对象结构包括非常多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其详细类的操作。
  2) 须要对一个对象结构中的对象进行非常多不同的而且不相关的操作。而你想避免让这些操作“污染”这些对象的类。
Visitor模式使得你能够将相关的操作集中起来 定义在一个类中。

  3) 当该对象结构被非常多应用共享时。用Visitor模式让每一个应用仅包括须要用到的操作。
  4) 定义对象结构的类非常少改变,但常常须要在此结构上定义新的操作。

改变对象结构类须要重定义对全部訪

问者的接口,这可能须要非常大的代价。

假设对象结构类常常改变,那么可能还是在这些类中定义这些操作较好。

public class Body {  
    public void accept(IVisitor visitor) {  
        visitor.visit(this);  
    }  
}  
public class Engine {  
    public  void accept(IVisitor visitor) {  
             visitor.visit(this);  
     }  
}  
public class Wheel {  
    private String name;  
    public Wheel(String name) {  
        this.name = name;  
    }  
    String getName() {  
        return this.name;  
    }  
    public  void accept(IVisitor visitor) {  
        visitor.visit(this);  
    }  
}  
public class Car {  
    private Engine  engine = new Engine();  
    private Body    body   = new Body();  
    private Wheel[] wheels   
        = { new Wheel("front left"), new Wheel("front right"),  
            new Wheel("back left") , new Wheel("back right")  };  
    public void accept(IVisitor visitor) {  
        visitor.visit(this);  
        engine.accept(visitor);  
        body.accept(visitor) ;   
        for (int i = 0; i < wheels.length; ++ i)  
            wheels[i].accept(visitor);  
    }  
}    

public interface IVisitor {  
    void visit(Wheel wheel);  
    void visit(Engine engine);  
    void visit(Body body);  
    void visit(Car car);  
}    
    
public class PrintVisitor implements IVisitor {   
    @Override  
    public void visit(Wheel wheel) {  
        System.out.println("Visiting " + wheel.getName() + " wheel");   
    }    
    @Override  
    public void visit(Engine engine) {  
        System.out.println("Visiting engine");  
    }    
    @Override  
    public void visit(Body body) {  
        System.out.println("Visiting body");  
    }    
    @Override  
    public void visit(Car car) {  
        System.out.println("Visiting car");  
    }   

}

------------------------样例2-----------------------

Visitor模式,在不改动已有程序结构的前提下,通过加入额外的“訪问者”来完毕对已有代码功能的提升。Visitor模式的组成结构:

  1) 訪问者角色(Visitor):声明一个訪问接口。

接口的名称和方法的參数标识了向訪问者发送请求的元素角色。这样訪问者就能够通过该元素角色的特定接口直接訪问它。

  2) 详细訪问者角色(Concrete Visitor):实现訪问者角色(Visitor)接口
  3) 元素角色(Element):定义一个Accept操作,它以一个訪问者为參数。
  4) 详细元素角色(Concrete Element):实现元素角色(Element)接口。
  5) 对象结构角色(Object Structure):这是使用Visitor模式必须的角色。它要具备下面特征:能枚举它的元素;能够提供一个高层的接口同意訪问者角色訪问它的元素;能够是一个组合(组合模式)或是一个集合,如一个列表或一个无序集合
public abstract class Customer {
private String customerId;
private String name;

public String getCustomerId() {
    return customerId;
}
public void setCustomerId(String customerId) {
   this.customerId = customerId;
}
public String getName() {
   return name;
}
public void setName(String name) {
   this.name = name;
}

//接受訪问者的訪问
public abstract void accept(Visitor visitor);

//企业客户
public class EnterpriseCustomer extends Customer {
 private String linkman;
 private String linkTelephone;
 private String registerAddress;
 public String getLinkman() {
    return linkman;
 }

 public void setLinkman(String linkman) {
  this.linkman = linkman;
 }

 public String getLinkTelephone() {
 return linkTelephone;
 }

 public void setLinkTelephone(String linkTelephone) {
 this.linkTelephone = linkTelephone;
 }

 public String getRegisterAddress() {
 return registerAddress;
 }

 public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
 }

 @Override
 public void accept(Visitor visitor) {
 //回调訪问者对象的方法
         visitor.visitEnterpriseCustomer(this);
  }
}

//个人客户
public class PersonalCustomer extends Customer {
 private String telephone;
 private int age;
 public String getTelephone() {
      return telephone;
 }

 public void setTelephone(String telephone) {
         this.telephone = telephone;
 }

 public int getAge() {
       return age;
 }
 public void setAge(int age) {
          this.age = age;
 }

 @Override
 public void accept(Visitor visitor) {
     //回调訪问者对象的方法
     visitor.visitPersonalCustomer(this);
     }
}

/**
 * 訪问者接口
 */
public interface Visitor {
    // 訪问企业客户。相当于给企业客户加入訪问者功能
    public void visitEnterpriseCustomer(EnterpriseCustomer ec);
    //訪问个人客户,相当于给个人客户加入訪问者的功能
    public void visitPersonalCustomer(PersonalCustomer pc);
}

/**
 * 详细的訪问者。实现对客户的偏好分析
 */
public class PredilectionAnalyzeVisitor implements Visitor {
  @Override
  public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
  // TODO 依据以往的购买历史、潜在购买意向,以及客户所在行业的发展趋势、客户的发展趋势等的分析
                System.out.println("如今对企业客户" + ec.getName() + "进行产品偏好分析");
  }

  @Override
  public void visitPersonalCustomer(PersonalCustomer pc) {
             System.out.println("如今对个人客户" + pc.getName() + "进行产品偏好分析");
  }
}

/**
 * 详细的訪问者,实现客户提出服务请求的功能
 */
public class ServiceRequestVisitor implements Visitor {
  @Override
public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
        // TODO 企业客户提出的详细服务请求
         System.out.println(ec.getName() + "企业提出服务请求");
}

@Override
public void visitPersonalCustomer(PersonalCustomer pc) {
       // TODO 个人客户提出的详细服务请求
      System.out.println("客户" + pc.getName() + "提出服务请求");
     }
}

public class ObjectStructure {
 /**
  * 要操作的客户集合
  */
 private Collection<Customer> col = new ArrayList<Customer>();
 /**
  * 提供client操作的高层接口,详细的功能由client传入的訪问者决定
  * @param visitor client须要的訪问者
  */
 public void handleRequest(Visitor visitor) {
         for(Customer cm : col) {
              cm.accept(visitor);
        }
 }

 /**
  * 组建对象结构,想对象中加入元素
  * 不同的对象结构有不同的构建方式
  * @param ele 增加到对象的结构元素
  */
 public void addElement(Customer ele) {
          this.col.add(ele);
     }
}

public class Client {
 public static void main(String[] args) {
ObjectStructure os = new ObjectStructure();
Customer cml = new EnterpriseCustomer();
cml.setName("钢铁侠");
os.addElement(cml);

Customer cm2 = new EnterpriseCustomer();
cm2.setName("CDE公司");
os.addElement(cm2);

Customer cm3 = new PersonalCustomer();
cm3.setName("美国佬");
os.addElement(cm3);

ServiceRequestVisitor srVisitor = new ServiceRequestVisitor();
os.handleRequest(srVisitor);

PredilectionAnalyzeVisitor paVisitor = new PredilectionAnalyzeVisitor();
os.handleRequest(paVisitor);

  WorthAnalyzeVisitor waVisitor = new WorthAnalyzeVisitor();
  os.handleRequest(waVisitor);
  }
}

设计模式之十五:訪问者模式(Visitor Pattern)的更多相关文章

  1. 设计模式之二十四:訪问者模式(Visitor)

    訪问者模式: 定义了一个作用于一个类的一些操作,訪问者模式同意在不改变类的前提下添加一些操作. Represent an operation to be performed on the elemen ...

  2. 设计模式入门之訪问者模式Visitor

    //訪问者模式定义:表示一个作用于某对象结构中的各个元素的操作,它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作. //从定义上看.这个模式跟装饰模式的定义非常类似(动态地给一个对象加入一 ...

  3. python设计模式第二十五天【访问者模式】

    1.应用场景 (1)将数据和行为进行分离,不同的角色具有不同的行为 2.代码实现

  4. JAVA设计模式之 訪问者模式【Visitor Pattern】

    一.概述 訪问者模式是一种较为复杂的行为型设计模式,它包括訪问者和被訪问元素两个主要组成部分.这些被訪问的元素通常具有不同的类型,且不同的訪问者能够对它们进行不同的訪问操作.在使用訪问者模式时,被訪问 ...

  5. 享元模式 FlyWeight 结构型 设计模式(十五)

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  6. PHP设计模式——訪问者模式

    声明:本系列博客參考资料<大话设计模式>,作者程杰. 訪问者模式表示一个作用于某对象结构中的各元素的操作. 它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: w ...

  7. 《Java设计模式》之訪问者模式

    訪问者模式是对象的行为模式.訪问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作须要改动的话,接受这个操作的数据结构则能够保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类 ...

  8. Java设计模式(三) Visitor(訪问者)模式及多分派场景应用

    基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要 ...

  9. JAVA设计模式之:訪问者模式

    訪问者模式: 一个作用于某对象结构中各元素的操作,使你能够在不改变各元素类数据结构的前提下添加作用于这些元素的新操作. 结构对象是訪问者模式必备条件.且这个结构对象必须存在遍历自身各个对象的方法. 适 ...

随机推荐

  1. [BZOJ4565][HAOI2016]字符合并(区间状压DP)

    https://blog.csdn.net/xyz32768/article/details/81591955 首先区间DP和状压DP是比较明显的,设f[L][R][S]为将[L,R]这一段独立操作最 ...

  2. loj6300 「CodePlus 2018 3 月赛」博弈论与概率统计

    link 题意: A和B玩游戏,每轮A赢的概率为p.现在有T组询问,已知A赢了n轮输了m轮,没有平局,赢一局A得分+1,输一局得分-1,问A得分期望值? $n+m,T\leq 2.5\times 10 ...

  3. Go语言特点

    作者:asta谢链接:https://www.zhihu.com/question/21409296/answer/18184584来源:知乎 1.Go有什么优势 可直接编译成机器码,不依赖其他库,g ...

  4. C++11中的raw string literals

    作为一名C++书看得少得可怜的新手,我一直没有勇气去系统地学习一下C++ 11添加的新特性.不过,平日里逛论坛,阅读大犇们的博客,倒是了解了一些.比如,这个帖子: 如何绕过g++ 4.8.1那个不能在 ...

  5. 【洛谷】2474:[SCOI2008]天平【差分约束系统】

    P2474 [SCOI2008]天平 题目背景 2008四川NOI省选 题目描述 你有n个砝码,均为1克,2克或者3克.你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系.你把其中两个砝码A ...

  6. 解决IE11下载文件 文件名乱码问题

    1.Win + R输入gpedit.msc打开组策略编辑器:(不会请看下图) 2.定位到计算机配置→管理模板→windows组件→Internet Explorer→自定义用户代理字符串(有些系统用的 ...

  7. QCon大会上推荐阅读的10本书

    QCon北京2014大会将于4月25-27日在北京国际会议中心盛大开幕.QCon是由@InfoQ 主办的全球顶级技术盛会.在此次盛会中,现场将有@人民邮电出版社-信息技术分社 主办的现场扫描二维码赠书 ...

  8. SQLite 一款轻型的数据库

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌入式的,而且目前已经在很多嵌入式产 ...

  9. Hibernate中的Session缓存问题

    1. Session 缓存: 1) . 在 Session 接口的实现中包括一系列的 Java 集合 , 这些 Java 集合构成了 Session 缓存 .          它用于存放 Sessi ...

  10. .Net高级技术——对象序列化

    对象序列化 “序列化是将一个对象保存到存储介质上或者将对象进行转换使之能够在网络上传送的行为”.通俗一点的解释,序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是从文件或者数据库中取出数 ...