访问者模式(Visitor Pattern) 访问者模式就是将对象和对象本身的动作解耦,让操作可以独自变化。
结构图:
角色
抽象访问者(Visitor):为每一个具体元素类声明一个具体访问者的操作。
具体访问者(Concrete Visitor):实现抽象访问者中的操作。可以有多个实现。
抽象元素(Element):接口申明一个 accept 方法表示接受访问者的访问。该方法必须有一个参数被声明为访问者接口类型。
具体元素(Concrete Element):实现接收方法。根据当前元素类将其调用重定向到相应访问者的方法。
适用场景:
对一个复杂对象结构譬如树中的所有元素执行某些操作,可使用访问者模式。
优点:
可以引入在不同类对象上执行的新行为,且无需对这些类做出修改,符合开闭原则
可以将同一行为的不同版本移到同一个类中。符合单一原则。
缺点:
增加修改元素需要修改所有的访问者。
代码(C#) 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 interface IComponent { void Accept (IVisitor visitor ) ; }class ConcreteComponentA : IComponent { public void Accept (IVisitor visitor ) { visitor.Visit(this ); } public string ShowA () { return "A" ; } }class ConcreteComponentB : IComponent { public void Accept (IVisitor visitor ) { visitor.Visit(this ); } public string ShowB () { return "B" ; } }interface IVisitor { void Visit (ConcreteComponentA component ) ; void Visit (ConcreteComponentB component ) ; }class ConcreteVisitorA : IVisitor { public void Visit (ConcreteComponentA component ) { Console.WriteLine($"ConcreteVisitorA + {component.ShowA()} " ); } public void Visit (ConcreteComponentB component ) { Console.WriteLine($"ConcreteVisitorA + {component.ShowB()} " ); } }class ConcreteVisitorB : IVisitor { public void Visit (ConcreteComponentA component ) { Console.WriteLine($"ConcreteVisitorB + {component.ShowA()} " ); } public void Visit (ConcreteComponentB component ) { Console.WriteLine($"ConcreteVisitorB + {component.ShowB()} " ); } } List<IComponent> components = new List<IComponent> { new ConcreteComponentA(), new ConcreteComponentB() }; IVisitor visitor1 = new ConcreteVisitorA();foreach (var item in components) { item.Accept(visitor1); }
最后 访问者模式函数重载在大部分是静态绑定的。也就是说,调用类的哪个重载函数,是在编译期间,由参数的声明类型决定的,而非运行时,根据参数的实际类型决定的。