访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
抽象访问者角色(Vistor):声明一个活多个访问操作,使得所有具体访问者必须实现的接口。
具体访问者角色(ConcreteVistor):实现抽象访问者角色中所有声明的接口。
抽象节点角色(Element):声明一个接受操作,接受一个访问者对象作为参数。
具体节点角色(ConcreteElement):实现抽象元素所规定的接受操作。
结构对象角色(ObjectStructure):节点的容器,可以包含多个不同类或接口的容器。
abstract class Element
{
public abstract void Accpet(IVisitor visitor);
public abstract void Print();
}
// 具体元素A
class ElementA : Element
{
public override void Accpet(IVisitor visitor)
{
visitor.Visit(this);
}
public override void Print()
{
Console.WriteLine("我是元素A");
}
}
// 具体元素B
class ElementB : Element
{
public override void Accpet(IVisitor visitor)
{
visitor.Visit(this);
}
public override void Print()
{
Console.WriteLine("我是元素B");
}
}
interface IVisitor
{
void Visit(ElementA element);
void Visit(ElementB element);
}
class Visitor : IVisitor
{
public void Visit(ElementA element)
{
element.Print();
}
public void Visit(ElementB element)
{
element.Print();
}
}
class ObjectStructure
{
private List<Element> elements = new List<Element>();
public List<Element> Elements
{
get { return elements; }
}
public ObjectStructure()
{
Random ran = new Random();
for (int i = 0; i < 6; i++)
{
int ranNum = ran.Next(10);
if (ranNum > 5)
{
elements.Add(new ElementA());
}
else
{
elements.Add(new ElementB());
}
}
}
}
调用
class Program
{
static void Main(string[] args)
{
ObjectStructure objectStructure = new ObjectStructure();
// 遍历对象结构中的对象集合,访问每个元素的Print方法打印元素信息
foreach (Element e in objectStructure.Elements)
{
e.Accpet(new Visitor());
}
Console.Read();
}
}
结果
我是元素B
我是元素A
我是元素A
我是元素B
我是元素A
我是元素B
类图
优点与缺点
访问者模式的优点:
- 访问者模式使得添加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,添加新的操作会变得很复杂。而使用访问者模式,增加新的操作就意味着添加一个新的访问者类。因此,使得添加新的操作变得容易。
- 访问者模式使得有关的行为操作集中到一个访问者对象中,而不是分散到一个个的元素类中。这点类似与"中介者模式"。
- 访问者模式可以访问属于不同的等级结构的成员对象,而迭代只能访问属于同一个等级结构的成员对象。
访问者模式的缺点:
- 增加新的元素类变得困难。每增加一个新的元素意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中添加相应的具体操作。
本文主要借鉴了《Gof设计模式》