随笔分类
访问者模式
Visitor
行为型之一
分离对象的数据和行为,可以在不修改已有类的情况下,增加新的操作
应用实例
比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)
根据软件设计的开闭原则(对修改关闭,对扩展开放),我们怎么样实现这种需求呢?
显然这里可以用到访问者模式
角色和职责
- 访问者角色(Visitor)
为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访间者就可以通过该元素角色的特定接口直接访问它。 - 具体访问者角色(Concrete Visitor) :
实现每个由访问者角色( Visitor)声明的操作 - 元素角色(Element):
定义一个Accept操作,它以一个访间者为参数 - 具体元素角色( Concrete Element) :
实现由元素角色提供的Accept操作 - 对象结构角色( Object Structure) :
这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素﹔可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。
/**
* 公园的组成部分
*/
public interface ParkElement {
//用来接收它的访问者
void accept(Visitor visitor);
}
/**
* 对象的结构角色
* 能够枚举它的组成元素
*/
public class Park implements ParkElement{
private ParkA parkA;
private ParkB parkB;
public Park(){
parkA = new ParkA();
parkB = new ParkB();
}
@Override
public void accept(Visitor visitor) {
//轮询得到该访问者的行为
visitor.visit(this);
parkA.accept(visitor);
parkB.accept(visitor);
}
}
public class ParkA implements ParkElement{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public class ParkB implements ParkElement{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public interface Visitor {
//不同的访问者的行为可能不同
void visit(Park park);
void visit(ParkA parkA);
void visit(ParkB parkB);
}
public class VisitorA implements Visitor{
@Override
public void visit(Park park) {
}
@Override
public void visit(ParkA parkA) {
System.out.println("清洁工A:负责公园区域A的打扫");
}
@Override
public void visit(ParkB parkB) {
}
}
public class VisitorB implements Visitor{
@Override
public void visit(Park park) {
}
@Override
public void visit(ParkA parkA) {
}
@Override
public void visit(ParkB parkB) {
System.out.println("清洁工B:负责公园区域B的打扫");
}
}
public class VisitorManager implements Visitor{
@Override
public void visit(Park park) {
System.out.println("管理者:已确认全部区域的打扫情况");
}
@Override
public void visit(ParkA parkA) {
System.out.println("管理者:已确认A区域的打扫情况");
}
@Override
public void visit(ParkB parkB) {
System.out.println("管理者:已确认B区域的打扫情况");
}
}
/**
* 清洁工A:负责公园区域A的打扫
* 清洁工B:负责公园区域B的打扫
* 管理者:已确认全部区域的打扫情况
* 管理者:已确认A区域的打扫情况
* 管理者:已确认B区域的打扫情况
*/
public class Client {
public static void main(String[] args) {
Park park = new Park();
VisitorA visitorA = new VisitorA();
park.accept(visitorA);
VisitorB visitorB = new VisitorB();
park.accept(visitorB);
VisitorManager visitorManager = new VisitorManager();
park.accept(visitorManager);
}
}