访问者模式
访问者模式
春天 2008-12-17 17:02:37 阅读140 评论0 字号:大中小 订阅
访问者模式包含;以下角色
- 抽象访问者(IVisitor):声明一个或多个访问操作,形成所有具体元素角色必须实现的接口。
- 具体访问者(Visitor):实现抽象访问者声明的所有接口
- 抽象节点(AbstractNode):接受访问者对象作为参量,声明一个接受操作。
- 具体节点(Node):实现抽象元素所规定的接受操作。
- 结构对象(ObjectStructure):可以遍历结构中的所有元素。
如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。反过来,如果这样一个系统的数据结构对象易于变化,经常要有新的数据对象增加进来的话,就不适合使用访问者模式。因为在访问者模式中增加新的节点很困难,要涉及到在抽象访问者和所有的具体访问者中增加新的方法。
访问者模式的优点
1、访问者模式使得增加新的操作变得很容易。
如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
2、访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。
迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
3、积累状态
每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。
访问者模式的缺点
1、增加新的节点类变得很困难。
每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2、破坏封装。
访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
{
public interface IVisitor
{
void Visit(NodeA node);
void Visit(NodeB node);
}
public abstract class AbstractNode
{
public abstract void Accept(IVisitor visitor);
}
public class VisitorA : IVisitor
{
public void Visit(NodeA node)
{
Console.Write("Visitor A invoke : "+node.OperationA());
}
public void Visit(NodeB node)
{
Console.Write("/r/nVisitor A invoke : "+node.OperationB());
}
}
public class VisitorB : IVisitor
{
public void Visit(NodeA node)
{
Console.Write("Visitor B invoke : "+node.OperationA());
}
public void Visit(NodeB node)
{
Console.Write("/r/nVisitor B invoke : "+node.OperationB());
}
}
public class NodeA : AbstractNode
{
public override void Accept(IVisitor ivisitor)
{
ivisitor.Visit(this);
}
public string OperationA()
{
return "NodeA is visited";
}
}
public class NodeB : AbstractNode
{
public override void Accept(IVisitor ivisitor)
{
ivisitor.Visit(this);
}
public string OperationB()
{
return "NodeB is visited";
}
}
public class ObjectStructure
{
private ArrayList nodes;
public ObjectStructure()
{
this.nodes=new ArrayList();
}
public void Action(IVisitor ivisitor)
{
foreach(AbstractNode node in nodes)
node.Accept(ivisitor);
}
public void Add(AbstractNode node)
{
this.nodes.Add(node);
}
}
public class Client
{
public static void Main()
{
ObjectStructure aObjects=new ObjectStructure();
aObjects.Add(new NodeA());
aObjects.Add(new NodeB());
IVisitor ivisitor=new VisitorA();
aObjects.Action(ivisitor);
}
}
}