你的位置:首页 > ASP.net教程

[ASP.net教程]设计模式学习笔记(二十一:访问者模式)


1.1概述

    表示将一个作用于某对象结构中的各个元素的操作。它可以在不改变各个元素的类的前提下定义作用于这些元素的新操作。这就是访问者模式的定义。

    编写类的时候,可能在该类中编写了若干个实例方法,该类的对象通过调用这些实例方法操作其成员变量表明所产生的行为。在某些设计中,可能需要定义作用于类的成员变量的新操作,而且这个新操作不应当由该类中的某个实例方法来承担。

  例如,有一个电表(Ammeter)类,在电表类中,electricAmount成员变量的值表示用电量,showElectricAmount()方法返回electricAmount变量的值来收取电费。现在的问题是:希望根据用电量来计算电费,即根据electricAmount变量的值来收取电费。显然,不应该在Ammeter类中增加计算电费的方法(单表本身不能计算出电费)。在实际生活中,应当由物业部门的“计表员”观察电表的用电量,然后按着有关收费标准计算出电费。访问者模式建议让一个称作访问者的对象访问Ammeter对象(电表),以便定义作用于Ammeter对象上的操作。在访问者模式中,“计表员”是AmmeterVisitor类的实例,称作Ammeter类实例的访问者,AmmeterVisitor类中有一个计算电费的方法:

void visit(Ammeter ammeter);

  该方法的参数是Ammeter类的实例,因此只要将Ammeter类的实例传递给该方法的参数,AmmeterVisitor类的实例就可以计算出电费(PS:假设1度点0.88元):

double visit(Ammeter ammer){

  charge = ammeter.showElectricAmount()*0.88;

  return charge;

}

  按着访问者模式,应当在Ammeter类中增加一个接受访问者的方法。Ammeter类中接受访问者的方法可如下定义:

void accept(AmmeterVisitor v){

  v.visit(this);          //将自身传递给参数指定的访问者

}

  因此,一个Ammeter类的实例通过调用accept()方法,并向该方法传递一个访问者,即AmmeterVisitor的实例,然后Ammeter类的实例再将自身传递给访问者就可以知道自己需要交纳多少电费了。Ammeter和AmmeterVisitor类的类图如下图一所示:

 

图一:有关缴纳电费关系类图(PS:类图画的有点不规范,仅作参考哦)

   Ammeter类有了接受访问者的accept(AmmeterVisitor visitor)方法后,可以不改变Ammeter类就能定义作用于Ammeter对象的成员变量上的新操作,比如,可以让accept(AmmeterVisitor visitor)的参数是AmmeterVisitor类的一个实例,该实例布局根据Ammeter对象的成员变量计算出正常的电费,而且还可以计算超电量应缴纳的额外电费。

 

 

1.2模式的结构

访问者模式包括以下五种角色:

(1)抽象元素(Element):一个抽象类,该类定义了接受访问者的accept操作。

(2)具体元素(Concrete Element):Element的子类。

(3)对象结构(Object Structure):一个集合,用于存放Element对象,提供遍历它自己的方法。

(4)抽象访问者(Visitor):一个接口,该接口定义操作对象(Concrete Element的实例)的方法。

(5)具体访问者(Concrete Visitor):实现Visitor接口的类。

访问者模式结构的类图如下图二所示:

 

图二:访问者模式的类图(PS:类图画的有点不规范,仅作参考哦)

 

 

1.3访问者模式的优点

(1)可以在不改变一个集合中元素类的情况下,增加新的施加于该元素上的新操作。

(2)可以将集合中各个元素的某些操作集中到访问者中,不仅便于集合的维护,也有利于集合中元素的复用。

 

 

1.4适合使用访问者模式的情景

(1)一个对象结构中,比如某个集合中,包含有很多对象,想对集合中对象增加新的操作。

(2)需要对集合中的对象进行很多不同并且不相关的操作,而又不想修改对象的类,就可以使用访问者模式。访问者模式可以在Visitor类中集中定义一些关于集合中对象的操作。