模式介绍
访问者模式允许我们通过将该操作表示为对象来操作对象。 因此,我们可以对所述对象进行操作而不改变那些对象的类或定义。
示例
我们有一家全市最好的餐馆,各种表现良好。领导决定给员工加薪放假,但由于某些原因,表示员工的类不能被修改。
员工类:
/// <summary>
/// The Element abstract class. All this does is define an Accept operation, which needs to be implemented by any class that can be visited.
/// </summary>
abstract class Element
{
public abstract void Accept(IVisitor visitor);
}
/// <summary>
/// The ConcreteElement class, which implements all operations defined by the Element.
/// </summary>
class Employee : Element
{
public string Name { get; set; }
public double AnnualSalary { get; set; }
public int PaidTimeOffDays { get; set; }
public Employee(string name, double annualSalary, int paidTimeOffDays)
{
Name = name;
AnnualSalary = annualSalary;
PaidTimeOffDays = paidTimeOffDays;
}
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
访问者接口:
/// <summary>
/// The Visitor interface, which declares a Visit operation for each ConcreteVisitor to implement.
/// </summary>
interface IVisitor
{
void Visit(Element element);
}
具体的访问者:
/// <summary>
/// A Concrete Visitor class.
/// </summary>
class IncomeVisitor : IVisitor
{
public void Visit(Element element)
{
Employee employee = element as Employee;
// We've had a great year, so 10% pay raises for everyone!
employee.AnnualSalary *= 1.10;
Console.WriteLine("{0} {1}'s new income: {2:C}", employee.GetType().Name, employee.Name, employee.AnnualSalary);
}
}
/// <summary>
/// A Concrete Visitor class
/// </summary>
class PaidTimeOffVisitor : IVisitor
{
public void Visit(Element element)
{
Employee employee = element as Employee;
// And because you all helped have such a great year, all my employees get three extra paid time off days each!
employee.PaidTimeOffDays += 3;
Console.WriteLine("{0} {1}'s new vacation days: {2}", employee.GetType().Name, employee.Name, employee.PaidTimeOffDays);
}
}
新的组合类:
/// <summary>
/// The Object Structure class, which is a collection of Concrete Elements. This could be implemented using another pattern such as Composite.
/// </summary>
class Employees
{
private List<Employee> _employees = new List<Employee>();
public void Attach(Employee employee)
{
_employees.Add(employee);
}
public void Detach(Employee employee)
{
_employees.Remove(employee);
}
public void Accept(IVisitor visitor)
{
foreach (Employee e in _employees)
{
e.Accept(visitor);
}
Console.WriteLine();
}
}
class LineCook : Employee
{
public LineCook() : base("Dmitri", 32000, 7)
{
}
}
class HeadChef : Employee
{
public HeadChef() : base("Jackson", 69015, 21)
{
}
}
class GeneralManager : Employee
{
public GeneralManager() : base("Amanda", 78000, 24)
{
}
}
客户端调用:
static void Main(string[] args)
{
// Who are my employees?
Employees e = new Employees();
e.Attach(new LineCook());
e.Attach(new HeadChef());
e.Attach(new GeneralManager());
// Employees are visited, giving them 10% raises and 3 extra paid time off days.
e.Accept(new IncomeVisitor());
e.Accept(new PaidTimeOffVisitor());
Console.ReadKey();
}
总结
访问者模式允许我们修改对象现有的实例而不修改原有类。所有这些实例都需要接受访问者对象并处理其内容。
源代码
https://github.com/exceptionnotfound/DesignPatterns/tree/master/Visitor
原文
https://www.exceptionnotfound.net/visitor-the-daily-design-pattern/