Visitor访问者模式:表示一个作用于某对象结构中的各元素的操作。它可以使你在不改变各元素类的前提下定义作用于这些元素的新操作。它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。
我们可以用一个形象点的例子来描述这个设计模式。都说男人有钱就变坏,女人有钱就拜拜;男人失败喝闷酒,女人失败泪汪汪;男人喜欢看NBA,女人喜欢逛淘宝……额,这只是一个形象的例子,不要太在意细节。。那么我们可以抽象这个例子中的几种不同的对象:男人、女人还有各自对同一件事的不同反应。
那这个例子和我们要讲述的访问者模式有什么关系呢?我们想知道的男人女人各自的行为就类似于一个个不同的访问者,男人女人自然就可以类比于我们想要访问的对象了。
UML图如下:
//抽象访问者
abstract class Visitor{
public abstract void VisitConcreteElementA(ConcreteElementA A);
public abstract void VisitConcreteElementB(ConcreteElementB B);
}
//具体访问者
class ConcreteVisitor:Visitor{
public override void VisitConcreteElementA(ConcreteElementA A){
Print(A);
}
public override void VisitConcreteElementB(ConcreteElementB B){
Print(B);
}
}
//抽象访问对象
abstract class Element{
public abstract void Accept(Visitor visitor);
}
//具体访问对象
class ConcreteElementA:Element{
public override void Accept(Visitor visitor){
visitor.VisitConcreteElementA(this);
}
}
//提供访问的统一接口
class ObjectStructure{
List<Element> elements = new List<Element>();
public void Attach(Element element){
elements.Add(element);
}
public void Detach(Element element){
elements.Remove(element);
}
public void Accept(Visitor visitor){
foreach( Element e in elements){
e.Accept(visitor);
}
}
}
//测试代码
static void Main(string[] args){
ObjectStructure os = new ObjectStructure();
os.attach(new ConcreteElementA());
ConcreteVisitor visitor = new ConcreteVisitor();
os.Accept(visitor);
Console.Read();
}
像上面的例子,假如再增加一种其他的行为,那不过只是增加一个继承自Visitor的类就可以了,但是假如再增加一个新的特殊的性别,那就必须对所有的继承自Visitor的类进行修改了……所以,访问者模式适用于数据结构相对稳定的系统。
访问者模式的优点在于增加新的操作(具体访问者)很容易,但缺点在于增加新的数据结构(具体访问对象)变得困难了。
参考书籍:《大话设计模式》