JAVA设计模式(二十二)——访问者模式

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">1、访问者模式</span>

        情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;
        Visitor模式也叫访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作。


2、应用场景

        比如有一个公园,有一到多个不同的组成部分;该公园存在多个访问者:清洁工A负责打扫公园的A部分,清洁工B负责打扫公园的B部分,公园的管理者负责检点各项事务是否完成,上级领导可以视察公园等等。也就是说,对于同一个公园,不同的访问者有不同的行为操作,而且访问者的种类也可能需要根据时间的推移而变化(行为的扩展性)。 根据软件设计的开闭原则(对修改关闭,对扩展开放),我们怎么样实现这种需求呢?


3、结构图示


4、角色职责

由上面的图示,大概可以得到如下的一些角色:

访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。 

具体访问者角色(Concrete Visitor):实现每个由访问者角色(Visitor)声明的操作。 

元素角色(Element):定义一个Accept操作,它以一个访问者为参数。 

具体元素角色(Concrete Element):实现由元素角色提供的Accept操作。

对象结构角色(Object Structure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。 


5、源码示例

首先来看一下访问者对象,访问者是一个抽象接口:

/* 
 * 访问者 
 */  
public interface Visitor {  
    public void visit(Park park);  
    public void visit(ParkA parkA);  
    public void visit(ParkB parkB);  
}

接下来,我们看看两个具体的访问对象:

/* 
 * 清洁工A,负责parkA的卫生情况 
 */  
public class VisitorA implements Visitor {  
  
    public void visit(Park park) {  
  
    }  
  
    public void visit(ParkA parkA) {  
        System.out.println("清洁工A:完成公园" + parkA.getName()+ "的卫生");  
    }  
  
    public void visit(ParkB parkB) {  
  
    }  
  
}

/* 
 * 清洁工B,负责公园B部分的卫生 
 */  
public class VisitorB implements Visitor {  
  
    public void visit(Park park) {  
  
    }  
  
    public void visit(ParkA parkA) {  
  
    }  
  
    public void visit(ParkB parkB) {  
        System.out.println("清洁工B:完成公园" + parkB.getName()+"的卫生");  
    }  
  
}

这里有一个管理员的访问者,如下:

public class VisitorManager implements Visitor {  
  
    public void visit(Park park) {  
        System.out.println("管理员:负责" + park.getName() + "卫生检查");  
    }  
  
    public void visit(ParkA parkA) {  
        System.out.println("管理员:负责公园"+ parkA.getName() +"部分卫生检查");  
    }  
  
    public void visit(ParkB parkB) {  
        System.out.println("管理员:负责公园"+ parkB.getName() +"分部卫生检查");  
    }  
  
} 

元素角色,抽象接口:

/* 
 * 公园每一部分的抽象 
 */  
public interface ParkElement {  
    //用来接纳访问者  
    public void accept(Visitor visitor);  
}

具体的元素接口,如上面的具体的访问者,这里只举例说明一个:

/* 
 * 公园的A部分 
 */  
public class ParkA implements ParkElement {  
    private String name;  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public void accept(Visitor visitor) {  
        visitor.visit(this);  
    }  
  
}

还有一个特殊的元素对象,类似访问者管理类,如下:

public class Park implements ParkElement {  
    private String name;  
    private ParkA parkA;  
    private ParkB parkB;  
      
    public Park() {  
        this.parkA = new ParkA();  
        this.parkB = new ParkB();  
        parkA.setName("A");  
        parkB.setName("B");  
    }  
  
    public void accept(Visitor visitor) {  
        visitor.visit(this);  
        parkA.accept(visitor);  
        parkB.accept(visitor);  
          
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
} 


6、结果分析

测试类如下:

public class MainClass {  
    public static void main(String[] args) {  
        Park park = new Park();  
        park.setName("白云公园");  
        VisitorA visitorA = new VisitorA();  
          
        park.accept(visitorA);  
          
        VisitorB visitorB = new VisitorB();  
        park.accept(visitorB);  
          
        VisitorManager visitorManager = new VisitorManager();  
        park.accept(visitorManager);  
    }  
}

结果如下:

清洁工A:完成公园A的卫生
清洁工B:完成公园B的卫生
管理员:负责白云公园卫生检查
管理员:负责公园A部分卫生检查
管理员:负责公园B分部卫生检查


7、模式总结

        访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。

        访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值