C# 设计模式-访问者模式
一.介绍
访问者模式(Visitor Pattern)。属于行为型模式。表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
二.实现
举个例子,如果有元素A、B类,想调用这些元素中的Print方法,很简单地,只要实例化去调用就可以。
public abstract class Element { public abstract void Print(); } public class ElementA : Element { public override void Print() { Console.WriteLine("PrintElementA"); } } public class ElementB : Element { public override void Print() { Console.WriteLine("PrintElementB"); } }
但需求不是一成不变的,如果同样的Print方法中,需要根据不同的用户去打印不同的内容,那只能对各个元素中的Print方法进行修改,这就不符合开闭原则。这里需要改变的东西仅仅是操作的内容,即Print方法的内容,元素A、B的结构都不需要改变。如果把操作和结构分离开来,不就可以解决这个问题?我们可以使用访问者模式来解决这类问题。
//抽象节点 public abstract class Element { public abstract void Print(Visitor visitor); } //具体节点 public class ElementA : Element { public override void Print(Visitor visitor) { visitor.PrintElementA(); } } //具体节点 public class ElementB : Element { public override void Print(Visitor visitor) { visitor.PrintElementB(); } } //抽象访问者 public abstract class Visitor { public abstract void PrintElementA(); public abstract void PrintElementB(); } //具体访问者 public class VisitorA : Visitor { public override void PrintElementA() { Console.WriteLine(this.GetType().Name + "\t" + "PrintElementA"); } public override void PrintElementB() { Console.WriteLine(this.GetType().Name + "\t" + "PrintElementB"); } } //具体访问者 public class VisitorB : Visitor { public override void PrintElementA() { Console.WriteLine(this.GetType().Name + "\t" + "PrintElementA"); } public override void PrintElementB() { Console.WriteLine(this.GetType().Name + "\t" + "PrintElementB"); } } //结构对象容器 public class ElementContainer { public List<Element> elements = new List<Element>(); public void Attach(Element element) { elements.Add(element); } public void Detach(Element element) { elements.Add(element); } public void Print(Visitor visitor) { foreach (var e in elements) { e.Print(visitor); } } } //调用 public static void Main(string[] args) { ElementContainer container = new ElementContainer(); container.Attach(new ElementA()); container.Attach(new ElementB()); container.Print(new VisitorA()); container.Print(new VisitorB()); }
访问者模式就是把Print的方法封装到访问者里,那如果以后Print方法的需求改变,只需要新建一个访问者来封装新的Print方法,那就不需要修改原有代码。
三.总结
优点:
1.访问者模式使得添加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,添加新的操作会变得很复杂。而使用访问者模式,增加新的操作就意味着添加一个新的访问者类。因此,使得添加一个新的操作变得容易。
2.访问者模式使得有关的行为操作集中于一个访问者对象中,而不是分散到一个个元素类中。
3.访问者模式可以访问属于不同的等级结构的成员对象,而迭代只能访问属于同一等级结构的成员对象。
缺点:
1.增加新的元素类变得困难。每增加一个新的元素意味着要在抽象访问者中添加一个新的抽象操作,并在每一个具体访问者中添加对应的具体操作。