【设计模式】—-(23)访问者模式(行为型)

本文介绍访问者模式的概念、适用场景及实现方式,并通过代码示例展示了如何利用访问者模式为对象结构中的元素添加新的操作,同时保持良好的扩展性和遵循单一职责原则。

今天来看最后一个设计模式——-访问者模式(行为型) 

——瞬间有一种忽如一夜春风来的感觉,明天总结下设计模式行为型的小结,然后再做个所有设计模式的总结。


一、定义(概念)

表示一个作用于某对象结构中的各元素的操作。
使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

二、适用场景

1、一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。
3、当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4、 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。


涉及角色:
1、访问者(Visitor):定义接口,声明一个或多个访问操作。 
2、具体访问者(ConcreteVisitor):实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。 
3、元素(Visitable):声明一个接受操作,接受一个访问者对象作为一个参数。 
4、具体元素结点(ConcreteElement):实现抽象结点所规定的接受操作。 
5、对象结构(ObjectStructure):
——能枚举它的元素
——可以提供一个更高层的接口以允许该访问者访问它的元素
——可以是一个复合
可以遍历结构中的所有元素,提供一个接口让访问者对象都可以访问每一个元素。 

三、UML



四、代码

抽象元素类
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. abstract class Element {    
  2.     public abstract void accept(IVisitor visitor);    
  3.     public abstract void doSomething();    
  4. }    
元素类
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. class ConcreteElement1 extends Element {    
  2.     public void doSomething(){    
  3.         System.out.println("这是元素1");    
  4.     }    
  5.         
  6.     public void accept(IVisitor visitor) {    
  7.         visitor.visit(this);    
  8.     }    
  9. }    
  10.     
  11. class ConcreteElement2 extends Element {    
  12.     public void doSomething(){    
  13.         System.out.println("这是元素2");    
  14.     }    
  15.         
  16.     public void accept(IVisitor visitor) {    
  17.         visitor.visit(this);    
  18.     }    
  19. }    
抽象访问者
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. interface IVisitor {    
  2.     public void visit(ConcreteElement1 el1);    
  3.     public void visit(ConcreteElement2 el2);    
  4. }    
访问者
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. class Visitor implements IVisitor {    
  2.     
  3.     public void visit(ConcreteElement1 el1) {    
  4.         el1.doSomething();    
  5.     }    
  6.         
  7.     public void visit(ConcreteElement2 el2) {    
  8.         el2.doSomething();    
  9.     }    
  10. }   
结构对象
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. class ObjectStruture {    
  2.     public static List<Element> getList(){    
  3.         List<Element> list = new ArrayList<Element>();    
  4.         Random ran = new Random();    
  5.         for(int i=0; i<10; i++){    
  6.             int a = ran.nextInt(100);    
  7.             if(a>50){    
  8.                 list.add(new ConcreteElement1());    
  9.             }else{    
  10.                 list.add(new ConcreteElement2());    
  11.             }    
  12.         }    
  13.         return list;    
  14.     }    
  15. }    
客户端
[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public class Client {    
  2.     public static void main(String[] args){    
  3.         List<Element> list = ObjectStruture.getList();    
  4.         for(Element e: list){    
  5.             e.accept(new Visitor());    
  6.         }    
  7.     }    
  8. }   
五、小结(优点与缺点)


优点:
符合单一职责原则:凡是适用访问者模式的场景中,元素类中需要封装在访问者中的操作必定是与元素类本身关系不大且是易变的操作,使用访问者模式一方面符合单一职责原则,另一方面,因为被封装的操作通常来说都是易变的,所以当发生变化时,就可以在不改变元素类本身的前提下,实现对变化部分的扩展。
扩展性良好:元素类可以通过接受不同的访问者来实现对不同操作的扩展。


缺点:
增加新的元素类比较困难。通过访问者模式的代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,也就是说,每增加一个元素类都需要修改访问者类(也包括访问者类的子类或者实现类),修改起来相当麻烦。也就是说,在元素类数目不确定的情况下,应该慎用访问者模式。所以,访问者模式比较适用于对已有功能的重构,比如说,一个项目的基本功能已经确定下来,元素类的数据已经基本确定下来不会变了,会变的只是这些元素内的相关操作,这时候,我们可以使用访问者模式对原有的代码进行重构一遍,这样一来,就可以在不修改各个元素类的情况下,对原有功能进行修改。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值