标签:blank 描述 打印 lis map 单一职责 array objects sys
定义:封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
类型:行为类模式
类图:
访问者模式可能是行为类模式中最复杂的一种模式了,但是这不能成为我们不去掌握它的理由。我们首先来看一个简单的例子,代码如下:
1 class A { 2 public void method1(){ 3 System.out.println("我是A"); 4 } 5 6 public void method2(B b){ 7 b.showA(this); 8 } 9 } 10 11 class B { 12 public void showA(A a){ 13 a.method1(); 14 } 15 }
我们主要来看一下在类A中,方法method1和方法method2的区别在哪里,方法method1很简单,就是打印出一句“我是A”;方法method2稍微复杂一点,使用类B作为参数,并调用类B的showA方法。再来看一下类B的showA方法,showA方法使用类A作为参数,然后调用类A的method1方法,可以看到,method2方法绕来绕去,无非就是调用了一下自己的method1方法而已,它的运行结果应该也是“我是A”,分析完之后,我们来运行一下这两个方法,并看一下运行结果:
1 public class Test { 2 public static void main(String[] args){ 3 A a = new A(); 4 a.method1(); 5 a.method2(new B()); 6 } 7 }
运行结果为:
我是A
我是A
看懂了这个例子,就理解了访问者模式的90%,在例子中,对于类A来说,类B就是一个访问者。但是这个例子并不是访问者模式的全部,虽然直观,但是它的可扩展性比较差,下面我们就来说一下访问者模式的通用实现,通过类图可以看到,在访问者模式中,主要包括下面几个角色:
访问者模式的通用代码实现
1 abstract class Element { 2 public abstract void accept(IVisitor visitor); 3 public abstract void doSomething(); 4 } 5 6 interface IVisitor { 7 public void visit(ConcreteElement1 el1); 8 public void visit(ConcreteElement2 el2); 9 } 10 11 class ConcreteElement1 extends Element { 12 public void doSomething(){ 13 System.out.println("这是元素1"); 14 } 15 16 public void accept(IVisitor visitor) { 17 visitor.visit(this); 18 } 19 } 20 21 class ConcreteElement2 extends Element { 22 public void doSomething(){ 23 System.out.println("这是元素2"); 24 } 25 26 public void accept(IVisitor visitor) { 27 visitor.visit(this); 28 } 29 } 30 class Visitor implements IVisitor { 31 32 public void visit(ConcreteElement1 el1) { 33 el1.doSomething(); 34 } 35 36 public void visit(ConcreteElement2 el2) { 37 el2.doSomething(); 38 } 39 } 40 41 class ObjectStruture { 42 public static List<Element> getList(){ 43 List<Element> list = new ArrayList<Element>(); 44 Random ran = new Random(); 45 for(int i=0; i<10; i++){ 46 int a = ran.nextInt(100); 47 if(a>50){ 48 list.add(new ConcreteElement1()); 49 }else{ 50 list.add(new ConcreteElement2()); 51 } 52 } 53 return list; 54 } 55 } 56 57 public class Client { 58 public static void main(String[] args){ 59 List<Element> list = ObjectStruture.getList(); 60 for(Element e: list){ 61 e.accept(new Visitor()); 62 } 63 } 64 }
访问者模式的优点
访问者模式的适用场景
假如一个对象中存在着一些与本对象不相干(或者关系较弱)的操作,为了避免这些操作污染这个对象,则可以使用访问者模式来把这些操作封装到访问者中去。
假如一组对象中,存在着相似的操作,为了避免出现大量重复的代码,也可以将这些重复的操作封装到访问者中去。
但是,访问者模式并不是那么完美,它也有着致命的缺陷:增加新的元素类比较困难。通过访问者模式的代码可以看到,在访问者类中,每一个元素类都有它对应的处理方法,也就是说,每增加一个元素类都需要修改访问者类(也包括访问者类的子类或者实现类),修改起来相当麻烦。也就是说,在元素类数目不确定的情况下,应该慎用访问者模式。所以,访问者模式比较适用于对已有功能的重构,比如说,一个项目的基本功能已经确定下来,元素类的数据已经基本确定下来不会变了,会变的只是这些元素内的相关操作,这时候,我们可以使用访问者模式对原有的代码进行重构一遍,这样一来,就可以在不修改各个元素类的情况下,对原有功能进行修改。
总结
正如《设计模式》的作者GoF对访问者模式的描述:大多数情况下,你并需要使用访问者模式,但是当你一旦需要使用它时,那你就是真的需要它了。当然这只是针对真正的大牛而言。在现实情况下(至少是我所处的环境当中),很多人往往沉迷于设计模式,他们使用一种设计模式时,从来不去认真考虑所使用的模式是否适合这种场景,而往往只是想展示一下自己对面向对象设计的驾驭能力。编程时有这种心理,往往会发生滥用设计模式的情况。所以,在学习设计模式时,一定要理解模式的适用性。必须做到使用一种模式是因为了解它的优点,不使用一种模式是因为了解它的弊端;而不是使用一种模式是因为不了解它的弊端,不使用一种模式是因为不了解它的优点。
转自:http://blog.csdn.net/zhengzhb/article/details/7489639
标签:blank 描述 打印 lis map 单一职责 array objects sys
原文地址:http://www.cnblogs.com/zl1991/p/7516194.html