访问者模式(visitor)c++版本(设计模式完)

这是大话设计模式中的访问者模式的c++版本

/*
 * visitor.cpp
 *
 *  Created on: Nov 16, 2017
 *      Author: clh01s@163.com
 *      访问者模式:表示一个作用于某对象结构中的各个元素的操作。
 *                它使你可以在不改变各个元素的类的前提下定义
 *                作用于这些元素的新操作。
 */

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Man;
class Woman;

//状态的抽象类
class Action
{
public:
    virtual ~Action(){}
    virtual void GetManConclusion(Man* concreteElement)=0;
    virtual void GetWomanConclusion(Woman* concreteElement)=0;
};

//男人女人的抽象类
class Person
{
public:
    virtual ~Person(){}
    //获得状态对象
    virtual void Accept(Action* visitor)=0;
};

class Man:public Person
{
public:
    //实现基类虚函数
    void Accept(Action* visitor) override
    {
        /* 首先在客户程序中将具体状态作为参数传递给
         * “男人”类完成了一次分派,然后“男人”类调
         * 用作为参数的“具体状态”中的方法“男人反应”
         * 同时将自己(this)作为参数传递进去,完成
         * 了二次分派。
         */
        visitor->GetManConclusion(this);
    }
    string GetGender(){return _gender;}
private:
    string _gender = "男人";
};

class Woman:public Person
{
public:
    //实现基类虚函数
    void Accept(Action* visitor) override
    {
        visitor->GetWomanConclusion(this);
    }
    string GetGender(){return _gender;}
private:
    string _gender = "女人";
};

//成功
class Success:public Action
{
public:
    void GetManConclusion(Man* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"成功时,背后多半有个伟大的女人。"<<endl;
    }

    void GetWomanConclusion(Woman* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"成功时,背后多半有个不成功的男人。"<<endl;
    }

};

//失败
class Failing:public Action
{
public:
    void GetManConclusion(Man* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"失败时,闷头喝酒,谁也不用劝。"<<endl;
    }

    void GetWomanConclusion(Woman* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"失败时,两眼泪汪汪,谁也劝不了。"<<endl;
    }

};

//恋爱
class Amativeness:public Action
{
public:
    void GetManConclusion(Man* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"恋爱时,不懂也要装懂。"<<endl;
    }

    void GetWomanConclusion(Woman* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"恋爱时,懂也要装不懂。"<<endl;
    }

};

//婚姻
class Marriage:public Action
{
public:
    void GetManConclusion(Man* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"结婚时,感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。"<<endl;
    }

    void GetWomanConclusion(Woman* concreteElement) override
    {
        cout<<concreteElement->GetGender()<<"结婚时,欣慰曰:爱情长跑路漫漫,婚姻保险保平安。"<<endl;
    }

};

//对象结构
class ObjectStructure
{
public:
    //添加
    void Attach(Person* person)
    {
        _elements.push_back(person);
    }

    //删除
    void Detach(Person* person)
    {
        if(!_elements.empty())
        {
            for(int i = 0;i != _elements.size();++i)
            {
                if(_elements[i] == person)
                {
                    _elements.erase(_elements.begin()+i);
                }
            }
        }else
        {
            cout<<"对象向量中没有元素请检查操作是否正确."<<endl;
        }
    }
    void Display(Action* visitor)
    {
        //遍历向量中存放的所有元素,调用accept
        for(auto i : _elements)
        {
            i->Accept(visitor);
        }
    }
private:
    vector<Person*> _elements;
};

int main()
{
    ObjectStructure object;
    object.Attach(new Man());
    object.Attach(new Woman());

    //成功反应
    Success* v1 = new Success();
    //显示反应
    object.Display(v1);
    //失败反应
    Failing* v2 = new Failing();
    //显示反应
    object.Display(v2);
    //恋爱反应
    Amativeness* v3 = new Amativeness();
    //显示反应
    object.Display(v3);
    //结婚反应
    Marriage* v4 = new Marriage();
    //显示反应
    object.Display(v4);

    return 0;
}

程序输出:

clh@clh:~/testcode/设计模式$ g++ visitor.cpp -std=c++11 -g
clh@clh:~/testcode/设计模式$ ./a.out 
男人成功时,背后多半有个伟大的女人。
女人成功时,背后多半有个不成功的男人。
男人失败时,闷头喝酒,谁也不用劝。
女人失败时,两眼泪汪汪,谁也劝不了。
男人恋爱时,不懂也要装懂。
女人恋爱时,懂也要装不懂。
男人结婚时,感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。
女人结婚时,欣慰曰:爱情长跑路漫漫,婚姻保险保平安。

以下内容摘抄自《设计模式》:
访问者模式适用性:
1.一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2.需要对一个对象结构中的对象进行很多不同且不相关的操作,而你想避免让这些操作“污染”这些对象的类,visitor使得你可以将相关的操作集中起来定义在一个类中。
3.定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,者可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作比较好。

访问者模式的优点:
1.访问者模式易于增加新的操作 访问者使得增加以来于复杂对象结构的构建的操作变得更容易了。仅需增加一个新的访问者即可在一个对象结构上定义一个新的操作。相反,如果每个功能都分散在多个类智商的话,定义新的操作时必须修改每一个类。
2.访问者集中相关的操作而分离无关的操作 相关的行为不是分布在定义该对象结构的各个类上,而是集中在一个访问者中。无关行为却被分别放在它们各自的访问者子类中。这就简化了这些元素的类,也简化了在这些访问者中定义的算法。所有与它的算法相关的数据结构都可以被隐藏在访问者中。
3.访问限制少 可以访问不具有相同父类的对象。可以对一个visitor接口增加任何类型的对象,它们不必继承相同的父类。
4.积累状态 当访问者访问对象结构中的每一个元素时,它可能会积累状态。如果没有访问者,这一状态将作为额外的参数传递给进行遍历的操作,或者定义为全局变量。

访问者模式的缺点:
1.增加新的ConcreteElement类很困难 visitor模式使得难以增加新的Element的子类。每添加一个新的ConcreteElement都要visitor中添加一个新的抽象操作,并在每一个ConcretVisitor类中实现相应操作。
2.破坏封装 访问者方法嘉定ConcreteElement接口的功能足够强,足以让访问者进行它们的工作。结果时,该模式常常迫使你提供访问元素内部状态的公共操作,这可能会破坏它们的封装性。

转载请注明源地址:http://blog.csdn.net/clh01s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值