设计模式 09 访问者模式

发布于 2021-06-12  54 次阅读


一、意图

    表示一个作用于对象结构体中的各元素操作。它使你可以再不改变元素的类的情况下定义作用于这些元素的新操作。
    人话:在不改变既有类时,为其增加新的功能。

二、和真实世界的类比

图1
图1:优秀的保险代理人总能为不同类型的团体提供不同的保单

    假如有这样一位非常希望赢得新客户的资深保险代理人。他可以拜访街区中的每栋楼,尝试向每个路人推销保险。所以,根据大楼内组织类型的不同,他可以提供专门的保单:
    如果建筑是居民楼,他会推销医疗保险。
    如果建筑是银行,他会推销失窃保险。
    如果建筑是咖啡厅,他会推销火灾和洪水保险。

三、UML

图2
图2:访问者模式结构

四、实例

    假设我们要对一个汽车零件装配厂的系统重构,他们的零件很少变化,价格经常变化,下面使用访问者模式来改进他们的系统。

图3
图3:类图

    在这个案例中,我们有5个产品,两个访问者分别访问他们的价格和描述。下面是代码:

#include <iostream>
#include <string>

class Crankcase;
class Carburetor;
class Whell;
class HeadlightBulb;
class Reflector;
class Engine;
class Headlight;

class Visitor
{
public:
    virtual void visit(const Crankcase* ele) const = 0;
    virtual void visit(const Carburetor* ele) const = 0;
    virtual void visit(const Whell* ele) const = 0;
    virtual void visit(const HeadlightBulb* ele) const = 0;
    virtual void visit(const Reflector* ele) const = 0;
    virtual void visit(const Headlight* ele) const = 0;
    virtual void visit(const Engine* ele) const = 0;
};

class CarPart
{
public:
    virtual std::string getDescription() const = 0;
    virtual void accept(Visitor* vis) const = 0;
};

class Engine : public CarPart
{
public:
    virtual std::string getDescription() const override
    {
        return "Engine";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class Whell : public CarPart
{
public:
    virtual std::string getDescription() const override
    {
        return "Whell";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class Headlight : public CarPart
{
public:
    virtual std::string getDescription() const override
    {
        return "Headlight";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class Crankcase : public Engine
{
public:
    virtual std::string getDescription() const override
    {
        return "Crankcase";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class Carburetor : public Engine
{
public:
    virtual std::string getDescription() const override
    {
        return "Carburetor";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class HeadlightBulb : public Headlight
{
public:
    virtual std::string getDescription() const override
    {
        return "HeadlightBulb";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class Reflector : public Headlight
{
public:
    virtual std::string getDescription() const override
    {
        return "Reflector";
    }

    virtual void accept(Visitor* vis) const override
    {
        vis->visit(this);
    }
};

class PriceVisitor : public Visitor
{
public:
    virtual void visit(const Crankcase* ele) const override
    {
        std::cout << 10 << std::endl;
    }

    virtual void visit(const Carburetor* ele) const override
    {
        std::cout << 20 << std::endl;
    }

    virtual void visit(const Whell* ele) const override
    {
        std::cout << 30 << std::endl;
    }

    virtual void visit(const HeadlightBulb* ele) const override
    {
        std::cout << 40 << std::endl;
    }

    virtual void visit(const Reflector* ele) const override
    {
        std::cout << 50 << std::endl;
    }

    virtual void visit(const Headlight* ele) const override
    {
        std::cout << 60 << std::endl;
    }

    virtual void visit(const Engine* ele) const override
    {
        std::cout << 70 << std::endl;
    }
};

class DesVisitor : public Visitor
{
public:
    virtual void visit(const Crankcase* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const Carburetor* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const Whell* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const HeadlightBulb* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const Reflector* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const Headlight* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }

    virtual void visit(const Engine* ele) const override
    {
        std::cout << ele->getDescription() << std::endl;
    }
};

void Client(CarPart* carpart, Visitor* vis)
{
    carpart->accept(vis);
}

int main()
{
    Visitor* priceVis = new PriceVisitor();
    Visitor* desVis = new DesVisitor();

    CarPart* whell = new Whell();
    Client(whell, priceVis);
    Client(whell, desVis);

    CarPart* engine = new Engine();
    Client(engine, priceVis);
    Client(engine, desVis);

    delete priceVis, desVis, whell, engine;

    return 0;
}