为什么';访客模式';要求每个类继承具有accept()函数的VisitorHost接口类? 我正在学习一种设计模式,Vistor模式,在C++中。

为什么';访客模式';要求每个类继承具有accept()函数的VisitorHost接口类? 我正在学习一种设计模式,Vistor模式,在C++中。,c++,design-patterns,C++,Design Patterns,首先,我复制下面的两个练习代码。第一个是“我的测试代码”,第二个是我课本中的“普通访问者模式”的简化代码。我希望您阅读第一个代码,但第二个代码只是普通访问者模式的参考代码 我的问题是,为什么访问者模式要求每个类继承具有虚拟函数accept()的VisitorsHostInterface类;如有必要,请参阅下面的第二个代码“正常访客模式”。在我的理解中,没有必要使用accept()函数来扫描所有实例,比如第一个代码“我的测试代码”。 我认为“我的测试代码”比“普通访问者模式”简单。 请告诉我访问者

首先,我复制下面的两个练习代码。第一个是“我的测试代码”,第二个是我课本中的“普通访问者模式”的简化代码。我希望您阅读第一个代码,但第二个代码只是普通访问者模式的参考代码

我的问题是,为什么访问者模式要求每个类继承具有虚拟函数accept()的VisitorsHostInterface类;如有必要,请参阅下面的第二个代码“正常访客模式”。在我的理解中,没有必要使用accept()函数来扫描所有实例,比如第一个代码“我的测试代码”。 我认为“我的测试代码”比“普通访问者模式”简单。 请告诉我访问者模式向每个类请求accept()函数的原因?多谢各位

(1) 我的测试代码

class ClassD;

class ClassC {
public:
    ClassC(int new_value, ClassD* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassC value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassD> next_object(void) { return next_object_; }
private:
    int value_=0;
    std::shared_ptr<ClassD> next_object_;
};

class ClassD {
public:
    ClassD(int new_value, ClassC* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassD value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassC> next_object(void) { return next_object_; }
private:
    int value_=0;
    std::shared_ptr<ClassC> next_object_;
};

class VisitorFuncInterface {
public:
    virtual ~VisitorFuncInterface() = default;
    virtual void visit(ClassC* obj) = 0;
    virtual void visit(ClassD* obj) = 0;
};

class VisitorFunc : public VisitorFuncInterface {
public:
    virtual ~VisitorFunc() = default;
    void visit(ClassC* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
    void visit(ClassD* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
};

void test_visitor_without_host(void) {

    ClassD* d0 = new ClassD(0, nullptr);
    ClassC* c0 = new ClassC(1, d0);
    ClassD* d1 = new ClassD(2, c0);

    VisitorFunc v;
    v.visit(d1);

    delete d1;

}
(2) 普通访客模式代码

class ClassA;
class ClassB;

class VisitorInterface {
public:
    virtual ~VisitorInterface() = default;
    virtual void visit(ClassA* obj) = 0;
    virtual void visit(ClassB* obj) = 0;
};

class VisitorsHostInterface {  // = visitor's host
public:
    virtual ~VisitorsHostInterface() = default;
    virtual void accept(VisitorInterface& v) = 0;
};

class VisitorsHost : public VisitorsHostInterface {
public:
    virtual ~VisitorsHost();
    void accept(VisitorInterface& v) {};
};

class ClassA : public VisitorsHostInterface {
public:
    ClassA(int new_value, ClassB* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassA value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassB> next_object(void) { return next_object_; }
    void accept(VisitorInterface& v) { v.visit(this); };
private:
    int value_=0;
    std::shared_ptr<ClassB> next_object_;
};

class ClassB : public VisitorsHostInterface {
public:
    ClassB(int new_value, ClassA* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassB value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassA> next_object(void) { return next_object_; }
    void accept(VisitorInterface& v) { v.visit(this); };
private:
    int value_=0;
    std::shared_ptr<ClassA> next_object_;
};

class Visitor : public VisitorInterface {
public:
    virtual ~Visitor() = default;
    void visit(ClassA* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
    void visit(ClassB* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
};

void test_visitor(void) {

    ClassB* b0 = new ClassB(0, nullptr);
    ClassA* a0 = new ClassA(1, b0);
    ClassB* b1 = new ClassB(2, a0);

    Visitor v;

    b1->accept(v);

    delete b1;

}

在您的示例中,您按值保存所有对象,并了解其静态和动态类型。您不需要动态分派,因此不需要有一个公共的
VisitorsHostInterface
基类。您的类只需要实现一个
accept
函数


但是,当您无法访问所访问对象的动态类型时,最常用的是访问者模式。假设您有一个
vecotr
。其中许多不同的
小部件
子类型通过指针存储。而不是
小部件
,它的每个子类都必须实现一个虚拟的
接受
功能。要获得对象的动态类型,您需要执行动态分派。

访问者模式有很多变化。为了更好地了解它,只需首先实现至少所有相关类的名称预先已知的情况。你应该设法避免这种情况下的所有铸造。
class ClassA;
class ClassB;

class VisitorInterface {
public:
    virtual ~VisitorInterface() = default;
    virtual void visit(ClassA* obj) = 0;
    virtual void visit(ClassB* obj) = 0;
};

class VisitorsHostInterface {  // = visitor's host
public:
    virtual ~VisitorsHostInterface() = default;
    virtual void accept(VisitorInterface& v) = 0;
};

class VisitorsHost : public VisitorsHostInterface {
public:
    virtual ~VisitorsHost();
    void accept(VisitorInterface& v) {};
};

class ClassA : public VisitorsHostInterface {
public:
    ClassA(int new_value, ClassB* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassA value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassB> next_object(void) { return next_object_; }
    void accept(VisitorInterface& v) { v.visit(this); };
private:
    int value_=0;
    std::shared_ptr<ClassB> next_object_;
};

class ClassB : public VisitorsHostInterface {
public:
    ClassB(int new_value, ClassA* new_next_object) : value_(new_value), next_object_(new_next_object) {};
    void print() { std::cout << "ClassB value_ = " << value_ << std::endl; }
    int value() { return value_; }
    std::shared_ptr<ClassA> next_object(void) { return next_object_; }
    void accept(VisitorInterface& v) { v.visit(this); };
private:
    int value_=0;
    std::shared_ptr<ClassA> next_object_;
};

class Visitor : public VisitorInterface {
public:
    virtual ~Visitor() = default;
    void visit(ClassA* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
    void visit(ClassB* obj) {
        if (obj) {
            obj->print();
            this->visit(obj->next_object().get());
        }
    }
};

void test_visitor(void) {

    ClassB* b0 = new ClassB(0, nullptr);
    ClassA* a0 = new ClassA(1, b0);
    ClassB* b1 = new ClassB(2, a0);

    Visitor v;

    b1->accept(v);

    delete b1;

}
ClassB value_ = 2
ClassA value_ = 1
ClassB value_ = 0