【设计模式】——访问者模式

访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

访问者模式结构图

  访问者模式使用与数据结构相对比较稳定的系统,即数据结构和作用与结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。其目的,要把处理从数据结构分离开来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。反之,如果这样的系统的数据结构对象易于变化,经常要有新的数据结构对象增加进来,就不适合使用访问者模式。

  访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。缺点是使增加新的数据结构变得困难了。

  其实,大多时候你并不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了。

#include <iostream>
#include <list>
using namespace std;
class ConcreteElementA;
class ConcreteElementB;
//Visitor类,为该对象结构中ConcreteElement的每一个类声明一个Visit操作
class Visitor
{
public:
    virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA)=0;
    virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB)=0;
};
//ConcreteVisitor1和ConcreteVisitor2类,具体访问者,实现每个由Visitor声明的操作。每个操作实现算法的一部分,
//而该算法片段乃是对应于结构中对象的类。
class ConcreteVisitor1:public Visitor
{
public:
    void VisitConcreteElementA(ConcreteElementA *concreteElementA)
    {
        cout << "ConcreteElementA被ConcreteVisitor1访问" << endl;
    }
    void VisitConcreteElementB(ConcreteElementB *concreteElementB)
    {
        cout << "ConcreteElementB被ConcreteVisitor1访问" << endl;
    }
};
class ConcreteVisitor2:public Visitor
{
public:
    void VisitConcreteElementA(ConcreteElementA *concreteElementA)
    {
        cout << "ConcreteElementA被ConcreteVisitor2访问" << endl;
    }
    void VisitConcreteElementB(ConcreteElementB *concreteElementB)
    {
        cout << "ConcreteElementB被ConcreteVisitor2访问" << endl;
    }
};
//Element类,定义一个Accept操作,它以一个访问者为参数
class Element
{
public:
    virtual void Accept(Visitor *visitor)=0;
};
//ConcreteElementA和ConcreteElementB类,具体元素,实现Accept操作
class ConcreteElementA:public Element
{
public:
    //充分利用双分派技术,实现处理与数据结构的分离
    void Accept(Visitor *visitor)
    {
        visitor->VisitConcreteElementA(this);
    }
    void OperationA()
    {
        cout << "具体元素A的其他相关方法" << endl;
    }
};
class ConcreteElementB:public Element
{
public:
    //充分利用双分派技术,实现处理与数据结构的分离
    void Accept(Visitor *visitor)
    {
        visitor->VisitConcreteElementB(this);
    }
    void OperationA()
    {
        cout << "具体元素B的其他相关方法" << endl;
    }
};
//ObjectStructure类,能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素
class ObjectStructure
{
private:
    list<Element*> m_list;
public:
    void Attach(Element *element)
    {
        m_list.push_back(element);
    }
    void Detach(Element *element)
    {
        m_list.remove(element);
    }
    void Accept(Visitor *visitor)
    {
        list<Element*>::iterator iter;
        for(iter=m_list.begin();iter!=m_list.end();iter++)
        {
            if(*iter!=NULL)
                (*iter)->Accept(visitor);
        }
    }
};
int main()
{
    ObjectStructure *o=new ObjectStructure();
    o->Attach(new ConcreteElementA());
    o->Attach(new ConcreteElementB());
    ConcreteVisitor1 *v1=new ConcreteVisitor1();
    ConcreteVisitor2 *v2=new ConcreteVisitor2();
    o->Accept(v1);
    o->Accept(v2);
    return 0;
}

  通常ConcreteVisitor可以单独开发,不必跟ConcreteElementA或ConcreteElementB写在一起。正因为这样,ConcreteVisitor能提高ConcreteElement之间的独立性,如果把一个处理动作设计成ConcreteElementA和ConcreteElementB类的方法,每次想新增“处理”以扩充功能时就得去修改ConcreteElementA和ConcreteElementB了。

下面是关于男人和女人的访问者模式例子

#include <iostream>
#include <list>
using namespace std;
class Man;
class Woman;
class Action
{
public:
    virtual void GetManConclusion(Man *concreteElementA)=0;
    virtual void GetWomanConclusion(Woman *concreteElementB)=0;
};
class Person
{
public:
    //获取状态对象
    virtual void Accept(Action *visiton)=0;
};
//这里的关键在于只分为男人和女人,这个性别的分类是稳定的,所以可以在状态类镇南关,增加“男人反应”和“女人反映”两个方法,方法个数
//是稳定的,不会很容易的发生变化。而“人”抽象类中有一个抽象方法“接受”,它是用来获得“状态”对象的。每一种具体状态都继承“状态”
//抽象类,实现两个反应方法
class Success:public Action
{
public:
    void GetManConclusion(Man *concreteElementA)
    {
        cout << "男人成功时,背后多半有一个伟大的女人。" << endl;
    }
    void GetWomanConclusion(Woman *concretementB)
    {
        cout << "女人成功时,背后大多有一个不成功的男人。" << endl;
    }
};
class Failing:public Action
{
public:
    void GetManConclusion(Man *concreteElementA)
    {
        cout << "男人失败时,闷头喝酒,谁也不用劝。" << endl;
    }
    void GetWomanConclusion(Woman *concretementB)
    {
        cout << "女人失败时,眼泪汪汪,谁也劝不了。" << endl;
    }
};
class Amativeness:public Action
{
public:
    void GetManConclusion(Man *concreteElementA)
    {
        cout << "男人恋爱时,凡是不懂也要装懂。" << endl;
    }
    void GetWomanConclusion(Woman *concretementB)
    {
        cout << "女人恋爱时,遇事懂也装作不懂。" << endl;
    }
};
class Man:public Person
{
public:
    void Accept(Action *visitor)
    {
        visitor->GetManConclusion(this);
    }
};
class Woman:public Person
{
public:
    void Accept(Action *visiton)
    {
        visiton->GetWomanConclusion(this);
    }
};
//对象结构
class ObjectStructure
{
private:
    list<Person*> m_list;
public:
    void Attach(Person *element)
    {
        m_list.push_back(element);
    }
    void Detach(Person *element)
    {
        m_list.remove(element);
    }
    void Display(Action *visitor)
    {
        list<Person*>::iterator iter=m_list.begin();
        for(;iter!=m_list.end();iter++)
        {
            if(NULL!=*iter)
                (*iter)->Accept(visitor);
        }
    }
};
int main()
{
    ObjectStructure *o=new ObjectStructure();
    o->Attach(new Man());
    o->Attach(new Woman());
    Success *v1=new Success();
    o->Display(v1);
    Failing *v2=new Failing();
    o->Display(v2);
    Amativeness *v3=new Amativeness();
    o->Display(v3);
    return 0;
}

【设计模式】——访问者模式

时间: 2024-10-12 01:21:06

【设计模式】——访问者模式的相关文章

.NET设计模式访问者模式

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它.2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口.3.Element 定义一个接受访问操作(accept

[我的设计模式] 访问者模式

访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式. 定义(源于GoF<Design Pattern>):表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法. 应用场景 用户访问博客.[我的设计模式] 访问者模式

【C#设计模式-访问者模式】

一.访问者模式的定义: 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. 二.访问者模式的结构和角色: 1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口. 3.Element 定义一个接受访问操作(acce

最复杂的设计模式---访问者模式

今天,我们一起来探讨最后一个.最复杂的设计模式 访问者模式:它表示一个作用于某个对象结构中的各个元素的操作.它使你可以在不改变个元素的类前提下,定义作用于这些元素的新操作.这个地方要注意:1.需要有个对象结构类用于存储循环遍历的方法的方式:2.访问者模式是对元素的操作:3.可以任意添加对这些元素的新操作.确实有点复杂,我们先看看其结构图: 代码部分: Visitor类抽象声明了对各种类型元素的访问方法: abstract class Visitor { public abstract void

C#设计模式-访问者模式

一.访问者模式介绍 1.1 访问者模式的定义 表示一个作用于某对象结构中的各个元素的操作.它使你可以在不改变各个元素的类的前提下定义作用于这些元素的新操作. 1.2 访问者模式的结构图 具体的访问者模式结构图如下所示. 这里需要明确一点:访问者模式中具体访问者的数目和具体节点的数目没有任何关系.从访问者的结构图可以看出,访问者模式涉及以下几类角色. 抽象访问者角色(Vistor):声明一个活多个访问操作,使得所有具体访问者必须实现的接口. 具体访问者角色(ConcreteVistor):实现抽象

小菜学设计模式——访问者模式

背景 最后一个设计模式,也是<大话设计模式>公认最难的设计模式,当然不是理解上困难,我觉得应该是使用上困难,这个设计模式虽然具有非常良好的扩展能力,但却需要类的结构早早定义清晰,试想,需求时刻变化,你的类可以稳定吗? 1.使用意图 容易扩展,满足开发封闭原则 2.生活实例 男人和女人的状态,把ConcreteElmentA看成男人,把ConcreteElementB看成女人,那么,所有的Visitor实例就是成功状态.失败状态.结婚状态.升职状态等.把这些状态放在客户端的集合中维护,一旦需要,

PHP设计模式——访问者模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 访问者模式表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作. UML类图: 角色: 1.抽象访问者(State):为该对象结构中具体元素角色声明一个访问操作接口.该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它. 2.具体访问者(Success):实现访问者声明的接口. 3.抽象元素(Person):定义一个接受访问操

深入浅出设计模式——访问者模式(Visitor Pattern)

模式动机 对于系统中的某些对象,它们存储在同一个集合中,且具有不同的类型,而且对于该集合中的对象,可以接受一类称为访问者的对象来访问,而且不同的访问者其访问方式有所不同,访问者模式为解决这类问题而诞生.在实际使用时,对同一集合对象的操作并不是唯一的,对相同的元素对象可能存在多种不同的操作方式.而且这些操作方式并不稳定,可能还需要增加新的操作,以满足新的业务需求.此时,访问者模式就是一个值得考虑的解决方案.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这

iOS设计模式---访问者模式

一个简单的Car模型,含有1台Engine.4个Wheel,使用访问者模式添加对Car的升级与维修操作. 定义Engine类: // //  NimoEngine.h //  VisitorDemo // //  Created by fu zheng on 15/8/12. //  Copyright (c) 2015年 FuZheng. All rights reserved. // #import <Foundation/Foundation.h> #import "NimoC

C++设计模式——访问者模式

访问者模式 在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问者模式把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化.该模式的目的是要把处理从数据结构分离出来.访问者模式让增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者.访问者模式将有关的行为集中到一个访问者对象中.现在再来说说我之前经历过的那个项目. 是基于Wi