原文
导读:访问者模式是我个人认为所有行为模式中最为复杂的一种模式了,这个模式可能看一遍会看不懂,我也翻了好几个例子,依然不能很好的理解访问者模式的核心。下面这个例子是来源于大话设计模式中的例子,稍作了修改!后续如果我有更好的例子或者想法我会对本章进行完善。
概述:
一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作(神一般的语言)。
结构图:
举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /// <summary> /// 抽象元素类:接口或者抽象类,声明接受哪一类访问者访问,程序上是通过accept方法中的参数来定义的。抽象元素一般有两类方法,一部分是本身的业务逻辑,另外就是允许接收哪类访问者来访问。 /// </summary> public abstract class Person { public abstract void Accept(Visitor visitor); } /// <summary> /// 元素类:实现抽象元素类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了。 /// </summary> public class Woman : Person { public override void Accept(Visitor visitor) { visitor.visit( this ); } } /// <summary> /// 元素类:实现抽象元素类所声明的accept方法,通常都是visitor.visit(this),基本上已经形成一种定式了。 /// </summary> public class Man : Person { public override void Accept(Visitor visitor) { visitor.visit( this ); } } /// <summary> /// 抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是visit方法中的参数定义哪些对象是可以被访问的 /// </summary> public interface Visitor { void visit(Man man); void visit(Woman girl); } /// <summary> /// 访问者:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。 /// 成功时Man与Woman的不同表现 /// </summary> public class Success : Visitor { public void visit(Man man) { Console.WriteLine( "当男人成功时,背后多半有一个伟大的女人" ); } public void visit(Woman woman) { Console.WriteLine( "当女人成功时,背后大多有一个不成功的男人" ); } } /// <summary> /// 访问者:实现抽象访问者所声明的方法,它影响到访问者访问到一个类后该干什么,要做什么事情。 /// 恋爱时Man与Woman的不同表现 /// </summary> public class Love : Visitor { public void visit(Man man) { Console.WriteLine( "当男人恋爱时,凡事不懂也装懂" ); } public void visit(Woman girl) { Console.WriteLine( "当女人恋爱时,遇事懂也装不懂" ); } } /// <summary> /// 结构对象:一个元素的容器,一般包含一个容纳多个不同类、不同接口的容器,如List、Set、Map等,在项目中一般很少抽象出这个角色 /// </summary> public class ObjectStructure { private List<Person> elements = new List<Person>(); public void attach(Person element) { elements.Add(element); } public void detach(Person element) { elements.Remove(element); } //遍历各种具体元素并执行他们的accept方法 public void display(Visitor visitor) { foreach (var item in elements) { item.Accept(visitor); } } } |
客户端调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Program { static void Main( string [] args) { ObjectStructure o = new ObjectStructure(); //依赖于ObjectStructure //实例化具体元素 o.attach( new Man()); o.attach( new Woman()); //当成功时不同元素的不同反映 Visitor success = new Success(); //依赖于抽象的Visitor接口 o.display(success); //当恋爱时的不同反映 Visitor amativeness = new Love(); //依赖于抽象的Visitor接口 o.display(amativeness); Console.ReadLine(); } } |
适用场景:
1、一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来 定义在一个类中。
3、当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4、定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
特点及优缺点:
1、访问者模式把数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
2、访问者模式适用于数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。
3、访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。
: