设计模式(23)——访问者 Visitor

来源:互联网 发布:sql server桌面图标 编辑:程序博客网 时间:2024/06/05 16:52

目录:

设计模式学习笔记首页
设计模式(1)——抽象工厂 AbstractFactory
设计模式(2)——生成器 Builder
设计模式(3)——工厂方法 Factory Method
设计模式(4)——原型 Prototype
设计模式(5)——单例 Singleton
设计模式(6)——适配器 Adapter
设计模式(7)——桥接 Bridge
设计模式(8)——组合 Composite
设计模式(9)——装饰 Decorator
设计模式(10)——外观 Facade
设计模式(11)——享元 Flyweight
设计模式(12)——代理 Proxy
设计模式(13)——职责链 Chain Of Responsibility
设计模式(14)——命令 Command
设计模式(15)——解释器 Interpreter
设计模式(16)——迭代器 Iterator
设计模式(17)——中介者 Mediator
设计模式(18)——备忘录 Memento
设计模式(19)——观察者 Observer
设计模式(20)——状态 State
设计模式(21)——策略 Strategy
设计模式(22)——模板方法 Template Method
设计模式(23)——访问者 Visitor

二十三、Visitor(访问者模式,对象行为型模式)

1. 意图:

  表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的前提下定义作用于这些元素的新操作。

2. 适用:

  1. 一个对象结构中包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  2. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor 使得你可以将相关的操作集中起来定义在一个类中。当该对象被很多应用共享时,用 Visitor 模式让每个应用仅包含需要用到的操作。
  3. 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

3. 类图:

image

4. 相关模式:

  Composite: 访问者可以用于对一个由 Composite 模式定义的对象结构进行操作。
  Interpreter: 访问者可以用于解释。

5. 思考:

  Visitor 模式可以使得Element在不修改自己的同时增加新的操作,但是这也带来了至少以下两个显著问题:

  1. 破坏了封装性。Visitor 模式要求 Visitor 可以从外部修改 Element 对象的状态,这一般通过两个方式来实现:
  2. Element 提供足够的 public 接口,使得 Visitor 可以通过调用这些接口达到修改 Element 状态的目的;
  3. Element 暴露更多的细节给 Visitor,或者让 Element 提供 public 的实现给 Visitor(当然也给了系统中其他的对象),或者将 Visitor 声明为 Element 的 friend 类,仅将细节暴露给 Visitor。但是无论哪种情况,特别是后者都将是破坏了封装性原则(实际上就是 C++ 的 friend 机制得到了很多的面向对象专家的诟病)。
  4. ConcreteElement 的扩展很困难:每增加一个 Element 子类,就要修改 Visitor 的接口,使得可以提供给这个新增加的子类的访问机制。

6. C++实现:

  1. 编写元素抽象基类 Element,包含一个纯虚函数(接口方法)Accept(Visitor* vis)
  2. 编写访问者抽象基类 Visitor,包含访问元素的方法 VisitConcreteElementA(Element* elm)VisitConcreteElementB(Element* elm)
  3. 元素的子类定义 Accept 函数,调用具体访问者的具体访问元素方法 VisitConcreteElementA(Element* elm)VisitConcreteElementB(Element* elm)

Visitor.h

//Visitor.h#pragma onceclass ConcreteElementA;class ConcreteElementB;class Element;class Visitor {public:    virtual ~Visitor();    virtual void VisitConcreteElementA(Element* elm) = 0;    virtual void VisitConcreteElementB(Element* elm) = 0;protected:    Visitor();private:};class ConcreteVisitorA : public Visitor {public:    ConcreteVisitorA();    virtual ~ConcreteVisitorA();    virtual void VisitConcreteElementA(Element* elm);    virtual void VisitConcreteElementB(Element* elm);protected:private:};class ConcreteVisitorB : public Visitor {public:    ConcreteVisitorB();    virtual ~ConcreteVisitorB();    virtual void VisitConcreteElementA(Element* elm);    virtual void VisitConcreteElementB(Element* elm);protected:private:};

Visitor.cpp

//Visitor.cpp#include "Visitor.h"#include "Element.h"#include <iostream>using namespace::std;Visitor::Visitor() {}Visitor::~Visitor() {}ConcreteVisitorA::ConcreteVisitorA() {}ConcreteVisitorA::~ConcreteVisitorA() {}void ConcreteVisitorA::VisitConcreteElementA(Element* elm) {    cout << "i will visit ConcreteElementA..." << endl;}void ConcreteVisitorA::VisitConcreteElementB(Element* elm) {    cout << "i will visit ConcreteElementB..." << endl;}ConcreteVisitorB::ConcreteVisitorB() {}ConcreteVisitorB::~ConcreteVisitorB() {}void ConcreteVisitorB::VisitConcreteElementA(Element* elm) {    cout << "i will visit ConcreteElementA..." << endl;}void ConcreteVisitorB::VisitConcreteElementB(Element* elm) {    cout << "i will visit ConcreteElementB..." << endl;}

Element.h

//Element.h#pragma onceclass Visitor;class Element {public:    virtual ~Element();    virtual void Accept(Visitor* vis) = 0;protected:    Element();private:};class ConcreteElementA : public Element {public:    ConcreteElementA();    ~ConcreteElementA();    void Accept(Visitor* vis);protected:private:};class ConcreteElementB : public Element {public:    ConcreteElementB();    ~ConcreteElementB();    void Accept(Visitor* vis);protected:private:};

Element.cpp

//Element.cpp#include "Element.h"#include "Visitor.h"#include <iostream>using namespace::std;Element::Element() {}Element::~Element() {}void Element::Accept(Visitor* vis){}ConcreteElementA::ConcreteElementA() {}ConcreteElementA::~ConcreteElementA() {}void ConcreteElementA::Accept(Visitor* vis) {    vis->VisitConcreteElementA(this);    cout << "visiting ConcreteElementA..." << endl;}ConcreteElementB::ConcreteElementB(){}ConcreteElementB::~ConcreteElementB() {}void ConcreteElementB::Accept(Visitor* vis) {    vis->VisitConcreteElementB(this);    cout << "visiting ConcreteElementB..." << endl;}

main.cpp

//main.cpp#include "Visitor.h"#include "Element.h"#include <iostream>using namespace::std;int main(int argc, char* argv[]) {    Visitor* vis = new ConcreteVisitorA();    Element* elm = new ConcreteElementA();    elm->Accept(vis);    return 0;}
阅读全文
0 0
原创粉丝点击