【转】设计模式学习笔记(23)-访问者

访问者模式(Visitor)表示一个作用于某对象结构的各元素的操作。它使你可以在不改变各元素的类的前提下定义下作用与这些元素的新操作。这个定义听着够抽象的,简单来说,访问者模式就像一个插入类内部的一个控制器,在不破坏类结构的情况下可以完全了解类内部结构并且做出一些改变。那它是怎么做到的呢?其实很简单,类首先预留一个接口,类似于上篇文章所说的钩子,将自己作为一个引用传给控制器,这样控制器就能在自己的范围内对该对象进行操作了。

举个例子吧,我们有一段文字进行处理,首先要过滤掉空白字符,然后将全角字符转换成半角字符,怎么办?你可以进行两次遍历。但是这种方法实在不是很优雅,如果有新的要求要提出来呢?就需要更改大量的代码。我们采用访问者模式,为每一个转换操作定义一个类,然后各有一个visit方法,在visit方法中将文档对象的引用传过去,由这些对象进行处理,这样一来耦合度就降低了。

访问者模式的类图如下:

Visitor是访问者类,定义所有访问者的接口,它有N个重载方法,ConcreteVisitorX是具体实现类,Element是具体visitor的操作对象,它也是一个接口,有几个实现类,它有一个accept方法来接受一个visitor。ObjectStructure是一堆Element的组合。

示例代码:

1
2
3
4
5
6
7
8
class ElementA;
class ElementB;
class Visitor
{
public:
    virtual void Visit(ElementA*) = 0;
    virtual void Visit(ElementB*) = 0;
};

定义Visitor接口

1
2
3
4
5
class Element
{
public:
    virtual void Accept(Visitor*) = 0;
};

定义一个Element

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ElementA : public Element
{
public:
    void Accept(Visitor* visitor) {
        visitor->Visit(this);
    }
    string GetName() {
        return "ElementA";
    }
};
class ElementB : public Element
{
public:
    void Accept(Visitor* visitor) {
        visitor->Visit(this);
    }
    string GetName() {
        return "ElementB";
    }
};

两个具体元素实现类

1
2
3
4
5
6
7
8
9
10
class VisitorA : public Visitor
{
public:
    void Visit(ElementA* element) {
        cout << element->GetName() << endl;
    }
    void Visit(ElementB* element) {
        cout << element->GetName() << endl;
    }
};

一个Visitor实现类,这里只写了一个

1
2
3
Visitor* visitor = new VisitorA();
Element* element = new ElementA();
element->Accept(visitor);

主方法这样调用
最后输出

1
2
ElementA
ElementB

结果理所当然。visitor模式所体现的易于增加新的操作体现在哪里呢?我们可以定义任意个Visitor子类对Element遍历处理,这是很容易做到的,而且所有相关操作全部集中在visitor中,使得逻辑更清晰。但是我们也发现了一个问题:visitor里那么多的visit重载方法,这意味着我们没增加一个element子类就必须添加一个visit方法,这改动还是相当大的,故在程序设计中要搞清楚那些是经常变化的,哪些不常变,以便区别对待。

我们来看看访问者模式的适用性吧:

  • 一个对象结构包含很多类对象,他们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作
  • 需要对一个对象结构中的对象进行很多不同的而且不相关的操作,而你想避免让这些操作污染这些对象的类
  • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。

在学习visitor模式中我们会遇到一个概念:单分派与多分派。我也没弄明白,以后有时间再仔细研究吧。

 

转自:http://lecoding.com/articles/272.html

posted on 2013-03-05 16:42  TheKingOfKingFish  阅读(126)  评论(0)    收藏  举报

导航