1. 定义
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。2. UML 类图
3. 结构代码
// Visitor pattern -- Structural example
|
using System; using System.Collections.Generic;
namespace DoFactory.GangOfFour.Visitor.Structural { ///<summary> /// MainApp startup class for Structural /// Visitor Design Pattern. ///</summary> classMainApp { staticvoid Main() { // Setup structure ObjectStructure o =new ObjectStructure(); o.Attach(newConcreteElementA()); o.Attach(newConcreteElementB());
// Create visitor objects ConcreteVisitor1 v1 =new ConcreteVisitor1(); ConcreteVisitor2 v2 =new ConcreteVisitor2();
// Structure accepting visitors o.Accept(v1); o.Accept(v2);
// Wait for user Console.ReadKey(); } }
///<summary> /// The 'Visitor' abstract class ///</summary> abstractclass Visitor { publicabstract void VisitConcreteElementA( ConcreteElementA concreteElementA); publicabstract void VisitConcreteElementB( ConcreteElementB concreteElementB); }
///<summary> /// A 'ConcreteVisitor' class ///</summary> classConcreteVisitor1 : Visitor { publicoverride void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.WriteLine("{0} visited by {1}", concreteElementA.GetType().Name,this.GetType().Name); }
publicoverride void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console.WriteLine("{0} visited by {1}", concreteElementB.GetType().Name,this.GetType().Name); } }
///<summary> /// A 'ConcreteVisitor' class ///</summary> classConcreteVisitor2 : Visitor { publicoverride void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.WriteLine("{0} visited by {1}", concreteElementA.GetType().Name,this.GetType().Name); }
publicoverride void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console.WriteLine("{0} visited by {1}", concreteElementB.GetType().Name,this.GetType().Name); } }
///<summary> /// The 'Element' abstract class ///</summary> abstractclass Element { publicabstract void Accept(Visitor visitor); }
///<summary> /// A 'ConcreteElement' class ///</summary> classConcreteElementA : Element { publicoverride void Accept(Visitor visitor) { visitor.VisitConcreteElementA(this); }
publicvoid OperationA() { } }
///<summary> /// A 'ConcreteElement' class ///</summary> classConcreteElementB : Element { publicoverride void Accept(Visitor visitor) { visitor.VisitConcreteElementB(this); }
publicvoid OperationB() { } }
///<summary> /// The 'ObjectStructure' class ///</summary> classObjectStructure { privateList<Element> _elements =new List<Element>();
publicvoid Attach(Element element) { _elements.Add(element); }
publicvoid Detach(Element element) { _elements.Remove(element); }
publicvoid Accept(Visitor visitor) { foreach (Element elementin _elements) { element.Accept(visitor); } } } } |
Output
ConcreteElementA visited by ConcreteVisitor1
ConcreteElementB visited by ConcreteVisitor1 ConcreteElementA visited by ConcreteVisitor2 ConcreteElementB visited by ConcreteVisitor2 |
4. 实例代码
// Visitor pattern -- Real World example
|
using System; using System.Collections.Generic;
namespace DoFactory.GangOfFour.Visitor.RealWorld { ///<summary> /// MainApp startup class for Real-World /// Visitor Design Pattern. ///</summary> classMainApp { ///<summary> /// Entry point into console application. ///</summary> staticvoid Main() { // Setup employee collection Employees e =new Employees(); e.Attach(newClerk()); e.Attach(newDirector()); e.Attach(newPresident());
// Employees are 'visited' e.Accept(newIncomeVisitor()); e.Accept(newVacationVisitor());
// Wait for user Console.ReadKey(); } }
///<summary> /// The 'Visitor' interface ///</summary> interfaceIVisitor { void Visit(Element element); }
///<summary> /// A 'ConcreteVisitor' class ///</summary> classIncomeVisitor : IVisitor { publicvoid Visit(Element element) { Employee employee = elementas Employee;
// Provide 10% pay raise employee.Income *= 1.10; Console.WriteLine("{0} {1}'s new income: {2:C}", employee.GetType().Name, employee.Name, employee.Income); } }
///<summary> /// A 'ConcreteVisitor' class ///</summary> classVacationVisitor : IVisitor { publicvoid Visit(Element element) { Employee employee = elementas Employee;
// Provide 3 extra vacation days Console.WriteLine("{0} {1}'s new vacation days: {2}", employee.GetType().Name, employee.Name, employee.VacationDays); } }
///<summary> /// The 'Element' abstract class ///</summary> abstractclass Element { publicabstract void Accept(IVisitor visitor); }
///<summary> /// The 'ConcreteElement' class ///</summary> classEmployee : Element { privatestring _name; privatedouble _income; privateint _vacationDays;
// Constructor public Employee(string name,double income, int vacationDays) { this._name = name; this._income = income; this._vacationDays = vacationDays; }
// Gets or sets the name publicstring Name { get {return _name; } set { _name =value; } }
// Gets or sets income publicdouble Income { get {return _income; } set { _income =value; } }
// Gets or sets number of vacation days publicint VacationDays { get {return _vacationDays; } set { _vacationDays =value; } }
publicoverride void Accept(IVisitor visitor) { visitor.Visit(this); } }
///<summary> /// The 'ObjectStructure' class ///</summary> classEmployees { privateList<Employee> _employees =new List<Employee>();
publicvoid Attach(Employee employee) { _employees.Add(employee); }
publicvoid Detach(Employee employee) { _employees.Remove(employee); }
publicvoid Accept(IVisitor visitor) { foreach (Employee ein _employees) { e.Accept(visitor); } Console.WriteLine(); } }
// Three employee types
classClerk : Employee { // Constructor public Clerk() : base("Hank", 25000.0, 14) { } }
classDirector : Employee { // Constructor public Director() : base("Elly", 35000.0, 16) { } }
classPresident : Employee { // Constructor public President() : base("Dick", 45000.0, 21) { } } } |
Output
Clerk Hank's new income: $27,500.00
Director Elly's new income: $38,500.00 President Dick's new income: $49,500.00 Clerk Hank's new vacation days: 14 Director Elly's new vacation days: 16 President Dick's new vacation days: 21 |
该文章来自:http://www.dofactory.com/Patterns/PatternVisitor.aspx