设计模式(22)访问者模式

百般思念 提交于 2020-02-14 00:58:59

模式介绍

访问者模式允许我们通过将该操作表示为对象来操作对象。 因此,我们可以对所述对象进行操作而不改变那些对象的类或定义。

示例

我们有一家全市最好的餐馆,各种表现良好。领导决定给员工加薪放假,但由于某些原因,表示员工的类不能被修改。

员工类:

/// <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/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!