C#设计模式——访问者模式(Visitor Pattern)

一、概述
由于需求的改变,某些类常常需要增加新的功能,但由于种种原因这些类层次必须保持稳定,不允许开发人员随意修改。对此,访问者模式可以在不更改类层次结构的前提下透明的为各个类动态添加新的功能。
二、访问者模式
访问者模式表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。其结构图如下:

Visitor为每一个ConcreteElement声明一个Visitor操作。
ConcreteVisitor实现了Visitor声明的操作,其定义的行为就是需要动态添加到ConcreteElement中的新功能。
Element定义一个以Visitor为参数的Accept操作。
ConcreteElement实现Accept操作。
ObjectStructure能枚举它的元素,可以提供一个高层接口以允许访问者访问它的元素。
访问者模式通过双重分派(double dispatch)的方法来透明的为各个类添加新的功能,第一重分派是指Accept方法的多态,第二重分派是指Visit方法的多态。
访问者模式的主要缺点在于增添新的Element子类的时候会导致Visitor类发生改变,而且随着Element子类的增加,Visitor类会越来越庞大。
三、示例
我们看一下访问者模式的简单应用。
首先定义一个公司的员工管理系统的基本员工类,这个类层次要求保持稳定,不得随意添加内容。对此就需要给这些类增加一个Accept方法用于将来的动态扩展。

复制代码
 1     public abstract class Emploree
 2     {
 3         public string Name { get; set; }
 4         protected Emploree() { }
 5         public Emploree(string name)
 6         {
 7             Name = name;
 8         }
 9         public abstract void Accept(Visitor visitor);
10     }
11 
12     public class Manager : Emploree
13     {
14         public Manager(string name)
15         {
16             Name = name;
17         }
18         public override void Accept(Visitor visitor)
19         {
20             visitor.Visit(this);
21         }
22     }
23 
24     public class Chairman : Emploree
25     {
26         public Chairman(string name)
27         {
28             Name = name;
29         }
30         public override void Accept(Visitor visitor)
31         {
32             visitor.Visit(this);
33         }
34     }
复制代码

在系统开发的某个时候,需要给员工增加获取工资待遇的方法,具体实现如下:

复制代码
 1     public abstract class Visitor
 2     {
 3         public abstract void Visit(Manager manager);
 4         public abstract void Visit(Chairman chairman);
 5     }
 6 
 7     public class Salary : Visitor
 8     {
 9         public override void Visit(Manager manager)
10         {
11             Console.WriteLine("Manager salary is 100000");
12         }
13         public override void Visit(Chairman chairman)
14         {
15             Console.WriteLine("Chairman salary is 1000000");
16         }
17     }
复制代码

这样,只需使用Emploree. Accept(new Salary())方法即可获取指定员工的工资。

posted @ 2016-10-28 15:14  星火卓越  阅读(1302)  评论(0编辑  收藏  举报