设计模式之十五:訪问者模式(Visitor Pattern)

訪问者模式(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);

}

}

时间: 2024-12-24 06:20:00

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

设计模式学习总结(21) 訪问者模式

本系列主要记录设计模式的意图是什么,它要解决一个什么问题,什么时候可以使用它:它是怎样解决的,掌握它的结构图,记住它的关键代码:可以想到至少两个它的应用实例,一个生活中的,一个软件中的:这个模式的优缺点是什么,其有哪些使用场景,在使用时要注意什么. 尊重作者,转载请注明晔阳的Bloghttp://blog.csdn.net/hacke2 21.訪问者模式 意图:主要讲数据结构与数据操作分离 主要解决:稳定的数据结构和易变的操作耦合问题 什么时候使用:与类本不相关的,为了避免这个污染 ,使用訪问者

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

訪问者模式: 定义了一个作用于一个类的一些操作,訪问者模式同意在不改变类的前提下添加一些操作. Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates. UML类图: 主要包括: Vis

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

//訪问者模式定义:表示一个作用于某对象结构中的各个元素的操作.它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作. //从定义上看,这个模式跟装饰模式的定义非常类似(动态地给一个对象加入一些额外的职责).可是装饰模式很多其它是在原有的基础上进行功能加强或者改动:而訪问者模式很多其它是为对象加入全新的功能.訪问者模式适合那些须要频繁为某些类加入新功能.新操作的项目. //模式结构: //Visitor:訪问者接口,为全部的訪问者对象声明一个visit方法,用来表示对对象结构加入的功能,

设计模式(十五):原型模式

早就发现java父类有个方法clone(),但一直没用过,也不知道怎么用.直到学习了原型设计模式才明白,他就是克隆方法,专门用来复制对象的.虽然到目前为止还没真正在项目中用到,但克隆方法还是挺有用的,它为我们创建相同对象带来了很大的便利,只要克隆一下就可以拥有一个全新的.初始值跟父类一样的对象. 一.概述 原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.看这些翻译过来的解释确实好别扭,简单理解就是复制对象,得到全新对象,这个全新对象拥有了跟老对象一

云计算设计模式(十五)——管道和过滤器模式

云计算设计模式(十五)——管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个应用程序可能需要执行各种关于它处理的信息不同复杂的任务.一个简单,但不灵活的方式来实施这个应用程序可以执行此处理为单一模块.然而,这种方法有可能减少用于重构代码,对其进行优化,或者重新使用它,如果是在应用程序中其他地方所需要的相同的处理的部件的机会. 图1通过使用单片式的方式示出了与处理数据的问题.

设计模式(十五):Iterator迭代器模式 -- 行为型模式

1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用户界面框架中的 Window 对象可以收集任意数量的控制对象 - Menu.Slider 和 Button.并且,集合的实现可以有多种方式:PHP 数字是一个集合,但也是一个散列表,一个链接列表,一个堆栈以及队列. 例子1:电视遥控器的频道遍历 2.问题 如何操纵任意的对象集合? 如一个列表(Lis

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

声明:本系列博客參考资料<大话设计模式>,作者程杰. 訪问者模式表示一个作用于某对象结构中的各元素的操作. 它使你能够在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamhxMDExMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" > 角色: 1.抽象訪问者(

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

訪问者模式是对象的行为模式.訪问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作须要改动的话,接受这个操作的数据结构则能够保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type):而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type).比方 [java] view plaincopyprint" class="About" href="

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

基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要取改动数据结构,也不必去改动原有的操作,而运行时再定义新的Visitor时闲着即可了(在操作加入上易拓展) 模式中角色分工 Visitor:抽象訪问者,在重载的visit函数中声明訪问者能够訪问的对象. Concrete Visitor:实现一个訪问者对于一个详细的元素的操作 Element:抽象元