设计模式之 Visitor - 访问者模式
Visitor模式也叫访问者模式,是由GoF提出的23种软件设计模式的一种。Visitor模式是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作。
本文介绍设计模式中的(Visitor)模式的概念,用法,以及实际应用中怎么样使用Visitor模式进行开发。
Visitor模式UML类图
Visitor
访问者抽象接口,通过visit(Element)方法访问Element(数据结构),完成对Element的操作行为。
ConcreteVisitor
访问者的具体实现类。
ObjectStructure
复合对象。包括所有需要被访问的数据结构对象(Element)。ObjectStructure本身也可以作为被访问者。
Element
元素,也就是被访问者。通过accept(Visitor)方法接受Visitor的访问。
ConcreteElement
Element的具体实现类。
比如有一个公园,有一到多个不同的组成部分;
该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。
也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。
根据软件设计的开闭原则(对修改关闭,对扩展开放),我们怎么样实现这种需求呢?
在这个例子中,如果我们在公园类里实现所有的访问者行为,势必造成以下问题:
1,由于所有的访问者的行为各不一样,在一个类中实现所有访问者行为,会造成该类功能过多,代码冗长。
2,不利于扩展。每增加一个访问者,就需要在已有的类里为其实现一个新的行为,就是说不得不修改已有的类,显然不符合软件设计开闭原则。
Visitor模式便可以解决这类问题。
当一个应用满足以下条件时,我们可以使用Visitor设计模式:
-一个对象可能存在一到多个数据元素
-存在多种行为,分别对不同的数据元素或数据的全体进行处理
-行为的不确定性或者说行为的扩展性
-分离对象的数据结构与行为,让不同的类完成不同的功能
-可以不修改已有类的基础上增加新的操作行为
-从另一个角度来看,同一个数据结构,为其实现不同的观察者,便可呈现不同的行为。
2,定义包含上述数据结构对象群的复合结构对象(相当于ObjectStructure角色)
3,定义Visitor抽象接口,定义所有访问行为方法(相当于Visitor角色)
4,定义具体的访问者对象,并实现所有visit方法(相当于ConcreteVisitor角色)
文件一览:
Client
测试类。
Visitable
相当于Element角色。
Park
公园类,包含ParkPartA与ParkPartB部分。相当于ObjectStructure以及ConcreteElement角色。
ParkPartA
公园的ParkPartA部分。相当于ConcreteElement角色。
ParkPartB
公园的ParkPartB部分。相当于ConcreteElement角色。
Visitor
访问者抽象接口。相当于Visitor角色。
VisitorCleanerA
负责打扫ParkPartA部分的清洁工类。相当于ConcreteVisitor角色。
VisitorCleanerB
负责打扫ParkPartA部分的清洁工类。相当于ConcreteVisitor角色。
VisitorManager
公园的管理人员类。相当于ConcreteVisitor角色。
代码:
/**
*TestVisitorPattern
*
*/
publicstaticvoidmain(String[]args){
//创建复合对象(公园对象)
Parkpark=newPark("Park");
//创建打扫A部分的清洁工访问者
System.out.println("---Visitor:CleanerA---");
VisitorvisitorCleanerA=newVisitorCleanerA();
park.accept(visitorCleanerA);
//创建打扫B部分的清洁工访问者
System.out.println("---Visitor:CleanerB---");
VisitorvisitorCleanerB=newVisitorCleanerB();
park.accept(visitorCleanerB);
//创建管理公园的管理人访问者
System.out.println("---Visitor:Manager---");
VisitorvisitorManager=newVisitorManager();
park.accept(visitorManager);
}
}
/**
*VisitorRole
*
*/
interfaceVisitor{
voidvisit(Parkpark);
voidvisit(ParkPartAparkPartA);
voidvisit(ParkPartBparkPartB);
}
/**
*ConcreteVisitor
*负责打扫ParkPartA部分的清洁工类
*
*/
classVisitorCleanerAimplementsVisitor{
publicvoidvisit(Parkpark){}
publicvoidvisit(ParkPartAparkPartA){
System.out.println("Clean"+parkPartA.name);
}
publicvoidvisit(ParkPartBparkPartB){}
}
/**
*ConcreteVisitor
*负责打扫ParkPartB部分的清洁工类
*
*/
classVisitorCleanerBimplementsVisitor{
publicvoidvisit(Parkpark){}
publicvoidvisit(ParkPartAparkPartA){}
publicvoidvisit(ParkPartBparkPartB){
System.out.println("Clean"+parkPartB.name);
}
}
/**
*ConcreteVisitor
*公园的管理人员类
*
*/
classVisitorManagerimplementsVisitor{
publicvoidvisit(Parkpark){
System.out.println("Check"+park.name);
}
publicvoidvisit(ParkPartAparkPartA){
System.out.println("Check"+parkPartA.name);
}
publicvoidvisit(ParkPartBparkPartB){
System.out.println("Check"+parkPartB.name);
}
}
/**
*ElementRole
*
*/
interfaceVisitable{
voidaccept(Visitorvisitor);
}
/**
*ObjectStructure&ConcreteElementRole
*公园类,包含ParkPartA与ParkPartB部分
*
*/
classParkimplementsVisitable{
Stringname;
ParkPartAparkPartA=newParkPartA("ParkPartA");
ParkPartBparkPartB=newParkPartB("ParkPartB");;
publicPark(Stringname){
this.name=name;
}
publicvoidaccept(Visitorvisitor){
visitor.visit(this);
parkPartA.accept(visitor);
parkPartB.accept(visitor);
}
}
/**
*ConcreteElementRole
*公园的一部分ParkPartA
*
*/
classParkPartAimplementsVisitable{
Stringname;
publicParkPartA(Stringname){
this.name=name;
}
publicvoidaccept(Visitorvisitor){
visitor.visit(this);
}
}
/**
*ConcreteElementRole
*公园的一部分ParkPartB
*
*/
classParkPartBimplementsVisitable{
Stringname;
publicParkPartB(Stringname){
this.name=name;
}
publicvoidaccept(Visitorvisitor){
visitor.visit(this);
}
}
执行Client,输出结果:
C:\Visitor>javaClient
---Visitor:CleanerA---
CleanParkA
---Visitor:CleanerB---
CleanParkB
---Visitor:Manager---
CheckPark
CheckParkA
CheckParkB
C:\Visitor>