设计模式之访问者模式

场景

​ 软件开发过程中,我们有一组数据,同时有对应的一组操作。我们希望可以根据需求,用任意的操作对任意的数据进行操作。使用访问者模式可以快速方便的实现这一需求。

定义

​ 访问者模式:封装一些施加于某种数据结构上的操作,一旦这些操作需要改变的话,接受这个操作的数据结构可以保持不变,反之亦然。

结构

​ 原型模式对被克隆的目标类进行封装,提供克隆接口。在c++中,我们通过拷贝构造来实现原型模式。模式结构:

  • Vistor(访问者):为对象结构中每一个 ConcreteElement 声明一个 visit() 操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型。
  • ConcreteVisitor(具体访问者):实现每个由 Visitor 声明的操作。
  • Element(元素):定义一个 accept() 操作,它通常以一个 Vistor 作为参数。
  • ConcreteElement(具体元素):实现 accept() 操作,通过调用 Visitor 的 visit() 方法来实现对元素的访问。
  • ObjectStructure(对象结构):能够枚举它的元素,同时提供一个高层的接口,以允许访问者访问它的元素。
实现

假设,小明、小刚一起切水果,水果有西瓜、哈密瓜。这是一个多对多的关系。
Vistor

class Watermelon;
class Cantaloupe;

class People{
  public:
    virtual ~People(){}
    virtual void cut(Watermelon*) = 0;
    virtual void cut(Cantaloupe*) = 0;
};

ConcreteVisitor

class xiaoming : public People{
  public:
   virtual void cut(Watermelon*) override {
       std::cout << "xiaoming cut watermelon!" << std::endl;
   }

   virtual void cut(Cantaloupe*) override {
       std::cout << "xiaoming cut cantaloupe!" << std::endl;
   }
};

class xiaogang : public People{
  public:
   virtual void cut(Watermelon*) override {
       std::cout << "xiaogang cut watermelon!" << std::endl;
   }

   virtual void cut(Cantaloupe*) override {
       std::cout << "xiaogang cut cantaloupe!" << std::endl;
   }
};

Element

class Fruit{
  public:
    virtual ~Fruit(){}
    virtual void Accept(People*) = 0;
};

ConcreteElement

class Watermelon : public Fruit{
  public:
    virtual void Accept(People* people){
        people->cut(this);
    }
};

class Cantaloupe : public Fruit{
  public:
    virtual void Accept(People* people){
        people->cut(this);
    }
};

ObjectStructure

class Kitchen{
  public:
    void Attach(Fruit* pFruit){m_fruit.push_back(pFruit);}
    void Detach(Fruit* pFruit){m_fruit.remove(pFruit);}

    void Accept(People * people){
        for(auto it = m_fruit.begin(); it != m_fruit.end(); ++it){
            (*it)->Accept(people);
        }
    }
  private:
    std::list<Fruit*> m_fruit;
};

Client:

int main(){
    Kitchen* pKitchen = new Kitchen();

    People* xiaoming = new xiaoming();
    People* xiaogang = new xiaogang();

    Fruit* Watermelon = new Watermelon();
    Fruit* Cantaloupe = new Cantaloupe();

    pKitchen->Attach(Watermelon);
    pKitchen->Attach(Cantaloupe);

    pKitchen->Accept(xiaoming);
    pKitchen->Accept(xiaogang);

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员之光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值