设计模式–访问者模式


记录有哪些水果品种

存储的水果代码结构

F:\WORKSPACE\WECODE
    ├─fruit/
        ├─fruit.h
        ├─fruit.cpp
    ├─main.cpp

具体实现细节

// fruit.h
#ifndef FRUIT_H
#define FRUIT_H

#include <iostream>
#include <unordered_map>
#include <string>

constexpr uint32_t FRUIT_APPALE = 1;
constexpr uint32_t FRUIT_ORANGE = 2;
constexpr uint32_t FRUIT_BALANCE = 3;

class Fruit {
public:
    Fruit();
    ~Fruit();
private:
    std::unordered_map<uint32_t, std::string> m_fruit;
};

#endif
// fruit.cpp
#include "fruit.h"
#include <string>

Fruit::Fruit()
{
    m_fruit[FRUIT_APPALE] = "I am apple " + std::to_string(FRUIT_APPALE);
    m_fruit[FRUIT_ORANGE] = "I am orange " + std::to_string(FRUIT_ORANGE);
    m_fruit[FRUIT_BALANCE] = "I am balance " + std::to_string(FRUIT_BALANCE);
}

Fruit::~Fruit() {}
// main.cpp
#include <iostream>
#include "fruit.h"

int main()
{
    Fruit fruit;
    return 0;
}

添加一个需求,查询有哪些水果,可以直接在Fruit中新增一个方法(一)

添加完需求之后,对应的代码结构

F:\WORKSPACE\WECODE
    ├─fruit/
        ├─fruit.h
        ├─fruit.cpp
    ├─main.cpp

具体实现细节

// fruit.h
#ifndef FRUIT_H
#define FRUIT_H

#include <iostream>
#include <unordered_map>
#include <string>

constexpr uint32_t FRUIT_APPALE = 1;
constexpr uint32_t FRUIT_ORANGE = 2;
constexpr uint32_t FRUIT_BALANCE = 3;

class Fruit {
public:
    Fruit();
    ~Fruit();

    void ShowAllFruit();

private:
    std::unordered_map<uint32_t, std::string> m_fruit;
};

#endif
// fruit.cpp
#include "fruit.h"
#include <string>

Fruit::Fruit()
{
    m_fruit[FRUIT_APPALE] = "I am apple " + std::to_string(FRUIT_APPALE);
    m_fruit[FRUIT_ORANGE] = "I am orange " + std::to_string(FRUIT_ORANGE);
    m_fruit[FRUIT_BALANCE] = "I am balance " + std::to_string(FRUIT_BALANCE);
}

Fruit::~Fruit() {}

void Fruit::ShowAllFruit()
{
    std::cout << "ShowAllFruit!!!" << std::endl;
    for (const auto &[fruitId, furitDes] : m_fruit) {
        std::cout << fruitId << " " << furitDes << std::endl;
    }
}
#include <iostream>
#include "fruit.h"
#include "show_fruit.h"

int main()
{
    Fruit fruit;
    fruit.ShowAllFruit();
    return 0;
}

点评

  • 需要同时修改main.cpp、fruit.cpp、fruit.h 不满足开闭原则
  • 后续新增其他查询操作,比如只显示苹果、香蕉等,还需要依旧改多出

添加一个需求,查询有哪些水果,可以直接在Fruit中新增一个方法(二)

存储的水果代码结构

F:\WORKSPACE\WECODE
    ├─fruit/
        ├─fruit_visit_if.h
        ├─fruit.h
        ├─fruit.cpp
    ├─visitor/
        ├─visit.h
        ├─show_fruit.h
        ├─show_fruit.cpp
    ├─main.cpp

具体实现细节

// fruit_visit_if.h

#ifndef FRUIT_VISIT_IF_H
#define FRUIT_VISIT_IF_H

#include <iostream>
#include <unordered_map>

class FruitVisitIf {
public:
    virtual const std::unordered_map<uint32_t, std::string>& GetAllFruit() const = 0;
};
#endif
// fruit.h

#ifndef FRUIT_H
#define FRUIT_H

#include <iostream>
#include <unordered_map>
#include <string>
#include "fruit_visit_if.h"
#include "visitor.h"

constexpr uint32_t FRUIT_APPALE = 1;
constexpr uint32_t FRUIT_ORANGE = 2;
constexpr uint32_t FRUIT_BALANCE = 3;

class Fruit : public FruitVisitIf {
public:
    Fruit();
    ~Fruit();

    void Accept(const Visitor &visitor) const;

    const std::unordered_map<uint32_t, std::string>& GetAllFruit() const override;

private:
    std::unordered_map<uint32_t, std::string> m_fruit;
};

#endif
// fruit.cpp

#include "fruit.h"
#include <string>

Fruit::Fruit()
{
    m_fruit[FRUIT_APPALE] = "I am apple " + std::to_string(FRUIT_APPALE);
    m_fruit[FRUIT_ORANGE] = "I am orange " + std::to_string(FRUIT_ORANGE);
    m_fruit[FRUIT_BALANCE] = "I am balance " + std::to_string(FRUIT_BALANCE);
}

Fruit::~Fruit() {}

void Fruit::Accept(const Visitor &visitor) const
{
    visitor.Visit(*this);
}

const std::unordered_map<uint32_t, std::string>& Fruit::GetAllFruit() const
{
    return m_fruit;
}
// visit.h

#ifndef VISITOR_H
#define VISITOR_H

#include "fruit_visit_if.h"

class Visitor {
public:
    virtual void Visit(const FruitVisitIf &fruit) const = 0;
};

#endif
// show_fruit.h

#ifndef SHOW_FRUIT_H
#define SHOW_FRUIT_H

#include "visitor.h"

class ShowFruit : public Visitor {
public:
    void Visit(const FruitVisitIf &fruit) const override;
};

#endif
// show_fruit.cpp

#include "show_fruit.h"
#include <iostream>
using namespace std;

void ShowFruit::Visit(const FruitVisitIf &fruit) const
{
    std::cout << "ShowAllFruit!!!" << std::endl;
    for (const auto &[fruitId, furitDes] : fruit.GetAllFruit()) {
        std::cout << fruitId << " " << furitDes << std::endl;
    }
}

点评

  • 后续新增其他查询操作,比如只显示苹果、香蕉等,可以得到适配

发表回复

您的电子邮箱地址不会被公开。