重温设计模式 --- 访问者模式

发布时间 2023-07-12 08:31:25作者: NiueryDiary

引言

访问者模式是一种行为型设计模式,它允许你在不修改对象结构的前提下定义作用于这些对象元素的新操作。它主要解决了在不修改已有类的前提下,对已有类中的对象进行新操作的问题。

访问者模式有以下几个主要角色:

  • 访问者(Visitor):访问者角色是一个抽象类或接口,其中定义了访问每个被访问元素时所需要执行的操作。具体访问者角色则实现了访问者接口,并根据需要实现其操作。

  • 被访问元素(Element):被访问元素角色是一个抽象类或接口,其中定义了接受访问者访问的接口。具体的被访问元素角色则实现了被访问元素接口,并实现其方法。

下面使用C#实现一个访问者模式:

定义访问者

// 访问者接口
interface IVisitor
{
    void Visit(ElementA element);
    void Visit(ElementB element);
}

// 具体访问者1
class ConcreteVisitor1 : IVisitor
{
    public void Visit(ElementA element)
    {
        Console.WriteLine("ConcreteVisitor1 is visiting ElementA");
    }

    public void Visit(ElementB element)
    {
        Console.WriteLine("ConcreteVisitor1 is visiting ElementB");
    }
}

// 具体访问者2
class ConcreteVisitor2 : IVisitor
{
    public void Visit(ElementA element)
    {
        Console.WriteLine("ConcreteVisitor2 is visiting ElementA");
    }

    public void Visit(ElementB element)
    {
        Console.WriteLine("ConcreteVisitor2 is visiting ElementB");
    }
}

在上面的示例中,访问者角色由接口IVisitor表示,其中定义了Visit方法,用于访问被访问元素。具体访问者ConcreteVisitor1ConcreteVisitor2则实现了IVisitor接口,并根据需要实现了Visit方法。

定义被访问元素

// 被访问元素接口
interface IElement
{
    void Accept(IVisitor visitor);
}

// 具体被访问元素A
class ElementA : IElement
{
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

// 具体被访问元素B
class ElementB : IElement
{
    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

被访问元素角色由接口IElement表示,其中定义了Accept方法,用于接受访问者的访问。具体的被访问元素ElementA和ElementB则实现了IElement接口,并实现了Accept方法,其中调用了访问者的Visit方法。

我们可以这样调用:

 // 创建被访问元素
 ElementA elementA = new ElementA();
 ElementB elementB = new ElementB();
 
 // 创建访问者
 IVisitor visitor1 = new ConcreteVisitor1();
 IVisitor visitor2 = new ConcreteVisitor2();
 
 // 访问被访问元素
 elementA.Accept(visitor1);
 elementA.Accept(visitor2);
 elementB.Accept(visitor1);
 elementB.Accept(visitor2);

输出:

ConcreteVisitor1 is visiting ElementA
ConcreteVisitor2 is visiting ElementA
ConcreteVisitor1 is visiting ElementB
ConcreteVisitor2 is visiting ElementB

示例中创建了被访问元素ElementA和ElementB,然后创建了访问者visitor1和visitor2。最后,分别调用了被访问元素的Accept方法,以及访问者的Visit方法,完成了访问操作。

:::tip{title="提示"}
需要注意的是,访问者是通过被访问元素的Accept方法进行访问的。因此,在访问者访问一个被访问元素时,该被访问元素会调用访问者的Visit方法,而不是访问者自行调用被访问元素的方法。
:::

结论

访问者模式的优点在于,它能够在不修改被访问元素的前提下,定义新的操作。同时,它也符合单一职责原则,因为每个具体的访问者只负责实现一个操作。但是,访问者模式的缺点在于,它增加了系统的复杂度,因为访问者需要了解被访问元素的内部结构,而且在被访问元素的结构发生变化时,需要修改访问者的代码。此外,访问者模式还可能导致循环依赖的问题,因为被访问元素和访问者都需要引用彼此的类。

总的来说,访问者模式是一种灵活的设计模式,可以用于在不修改已有类的前提下,定义新的操作。它的应用场景包括编译器、XML解析器、图形界面组件等需要对对象结构进行操作的系统。