- 什么是访问者模式
- 访问者模式的例子
- 访问者模式的优缺点
- 访问者模式的使用场景
- 闲言碎语
什么是访问者模式
相信每个IT公司服务器中的数据都是十分珍贵的内容.因此每个公司都有自己的规章制度去防止数据被他人的任意操作.因此,我们公司用对每次的服务器的操作都要进行纸质的记录.每次上机都要对使用人和使用时间进行记录(每台服务器都有一个专用的小本子进行记录).以便出现问题后可以定位到人.在编程的过程中我们也会遇到对对象添加新的操作和功能时候,如何尽可能不修改对象的类的一种方法,但又不希望修改她的内部方法.这时我们就要用到访问者模式.
意图:表示一个作用于某对象结构中的各元素的操作,它使你在不改变各元素的类的前提下定义作用于这些元素的新操作。
应用:作用于编译器语法树的语义分析算法。
UML:
抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。
具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。
具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。
结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。
访问者模式的例子
package com.designPattern.visitor6;
/**
* 我们访问记录册的接口(被访问者的接口)
*
* @author jason
*
*/
public interface Text {
/**
* 接受外部访问者的方法
*
* @param peason
*/
public void accept(Peason peason);
}
package com.designPattern.visitor6;
/**
* 人员的接口
*
* @author jason
*
*/
public interface Peason {
// 人员登记操作记录(原本对文本进行记录是在text进行的方法,通过此方法将任务由Peason完成)
public void record();// 优势:不同的人完成自己的记录.当有新的人时.不用修改text
}
package com.designPattern.visitor6;
/**
* 服务器使用记录的本子(具体的被访问者)
*
* @author jason
*
*/
public class ComputerText implements Text {
@Override
public void accept(Peason peason) {
// TODO Auto-generated method stub
peason.record();
}
}
package com.designPattern.visitor6;
public class ItEnginner implements Peason {
private String name;
private int time;
@Override
public void record() {
System.out.println("it工程师" + name + "使用服务器" + time + "小时!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ItEnginner(String name, int time) {
super();
this.name = name;
this.time = time;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
package com.designPattern.visitor6;
/**
* 具体的访问者
*
* @author jason
*
*/
public class OperationPeason implements Peason {
public OperationPeason(String name, int time) {
super();
this.name = name;
this.time = time;
}
private String name;
private int time;
@Override
public void record() {
System.out.println("运维工程师" + name + "使用服务器" + time + "小时!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
package com.designPattern.visitor6;
import java.util.LinkedList;
import java.util.List;
/**
* 对人员进行管理的类
*
* @author jason
*
*/
public class TextStructure {
List<Text> texts = new LinkedList<Text>();
/**
* 对访问者进行遍历
*/
public void useComputer(Peason peason) {
for (Text test : texts) {
test.accept(peason);
}
}
/**
* 清除访问者
*/
public void clearText() {
texts.clear();
}
/**
* 添加访问者
*
* @param peason
*/
public void addText(Text text) {
texts.add(text);
}
}
测试类package com.designPattern.visitor6;
import org.junit.Test;
/**
* 测试类
*
* @author jason
*
*/
public class TestCase {
@Test
public void test() {
TextStructure structure = new TextStructure();
Text computerText = new ComputerText();
structure.addText(computerText);
structure.useComputer(new ItEnginner("李红", 1));
structure.useComputer(new OperationPeason("王伟", 2));
}
}
访问者模式的优缺点
优点:
1:访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
2:访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
3:访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
4:积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。
缺点
1:增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2:破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的
访问者模式的使用场景
1:一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
闲言碎语