访问者模式 -- 大话设计模式
在今天,读书有时是件“麻烦”事。它需要你付出时间,付出精力,还要付出一份心境。--仅以《大话设计模式》来祭奠那逝去的……
访问者模式:表示作用于某对象结构中的各元素操作。它使你可以在不改变各元素类的前提下作用于这些元素的新操作
大多时候你并不需要访问者模式,但当你一旦需要访问者模式时,那就真的需要它了
1.男人和女人的区别
男人成功时,背后往往有一个伟大的女人;女人成功时,背后往往有一个不成功的男人;
将成功、失败和结婚等抽象成状态类,再定义一个人类抽象类(该抽象类,并非真正的人类抽象类,并不包含人类所具有的属性和行为)
/// <summary> /// 人类抽象类(并非真正的人类抽象类,并不包含人类所具有的属性和行为) /// </summary> public abstract class PersonElement { /// <summary> /// 定义一个accept操作,它以一个访问者为参数 /// </summary> public abstract void Accept(Action visitor); } /// <summary> /// 状态抽象类(将男人或者女人的结论、反应抽象为状态) /// </summary> public abstract class Action { public abstract void GetManConclusion(ManElement elementA); public abstract void GetWomanConclusion(WomanElement elementB); }
定义成功、失败和结婚等状态类
/// <summary> /// 成功(PersonElement成功的Action) /// </summary> public class Success : Action { public override void GetManConclusion(ManElement elementA) { Console.WriteLine("男人成功时,背后多半有一个伟大的女人"); } public override void GetWomanConclusion(WomanElement elementB) { Console.WriteLine("女人成功时,背后多半有一个不成功的男人"); } }
定义“男人”和“女人”,当他们接受Actoin所访问时,做出相应处理(这里包含一个双分派技术,首先客户端程序中将具体的Action作为参数传给了“男人”完成了一次分派,然后“男人”调用参数所拥有的获取男人反应行为,将自己this作为参数传递了进去,完成第二次分派)
/// <summary> /// 男人类 /// </summary> public class ManElement : PersonElement { public override void Accept(Action visitor) { visitor.GetManConclusion(this); } } /// <summary> /// 女人类 /// </summary> public class WomanElement : PersonElement { public override void Accept(Action visitor) { visitor.GetWomanConclusion(this); } }
由于总是需要“男人”和”女人“在不同的状态对比,因此定义该类进行遍历,得到不同的反应(客户端调用时,可以使用也可以不使用)
/// <summary> /// 对象结构类(由于总是需要“男人”和”女人“在不同的状态对比,因此定义该类进行遍历,得到不同的反应) /// </summary> public class ObjectStructure { private IList<PersonElement> elements = new List<PersonElement>(); /// <summary> /// 添加元素 /// </summary> public void Attach(PersonElement element) { elements.Add(element); } /// <summary> /// 移除元素 /// </summary> public void Detach(PersonElement element) { elements.Remove(element); } /// <summary> /// 查看显示 /// </summary> public void Display(Action visitor) { foreach (var v in elements) { v.Accept(visitor); } } }
开启场景模拟
static void Main(string[] args) { //面对成功 Success v1 = new Success(); //男人的结果 new ManElement().Accept(v1); //女人的结果 new WomanElement().Accept(v1); //使用结构对象进行遍历 ObjectStructure o = new ObjectStructure(); o.Attach(new ManElement()); o.Attach(new WomanElement()); o.Display(v1); }