【问题标题】:Template method pattern mess模板方法模式混乱
【发布时间】:2013-12-31 02:46:32
【问题描述】:

这里的钩子函数本身需要检查也属于类层次结构的数据成员的typeid。因此,我为该类层次结构定义了一个模板方法。这是我遇到的烂摊子:

void Person::leave() {
    // code
    hook();  // private virtual 
    // code
}

void Girl::hook() {  // Girl is a derived class of Person, with data member location 
                 // of type Location which itself has a derived class House
    // code
    location.locationHook(this);// what happens here depends on what kind of location she is in
    // code
}

void Location::locationHook(Person* person) {
    // Oh oh!  This depends on what class person is
}

void House::locationHook(Person* person) {
    // Oh oh!  This depends on what class person is

}

所以对于这种情况,我必须求助于我原来的方法,即为每种类型的 Person 派生类使用 typeid(*person) 和 dynamic_cast 和 if 语句来定义虚拟 locationHook,对吗?

【问题讨论】:

  • 请添加语言标签(可能是c++)并说明“模板方法”是指“模板方法模式”(可能)还是C++模板。

标签: c++ hook template-method-pattern


【解决方案1】:

这是我想出的解决方案。我测试了它是否有效,但我不知道它是否获得任何批准(或者它是否会一直有效):

void Person::leave() {
    // code
    hook();
}

void Person::hook() {
    // code
    location.locationHook (this);
}

void Girl::hook() {
    // code 
    location.locationHook (this);
}

void Location::locationHook (Person* person) {
    // code
    person->removeFromLocation();
}

void House::locationHook (Person* person) {
    // code 
    person->removeFromHouse();
}

// removeFromLocation() and removeFromHouse() are also virtual functions of Person

【讨论】:

    【解决方案2】:

    这是使用双重调度的替代解决方案:

    #include <iostream>
    #include <list>
    
    struct Person;  struct Girl;  struct Guy;
    
    struct Location {
        virtual void hook (Person*) = 0;
        virtual void hook (Girl*) = 0;
        virtual void hook (Guy*) = 0;
    };
    
    struct House : Location {
        virtual void hook (Person*) override;
        virtual void hook (Girl*) override {
            std::cout << "Girl left the house.\n";
        }
        virtual void hook (Guy*) override {
            std::cout << "Guy left the house.\n";
        }
    };
    
    struct Person {
        Location* location = new House;
        void leave() {
            // ...
            hook();
            // ...
        }
        virtual void invoke_hook (Location*) = 0;
    private:
        virtual void hook() = 0;
    };
    
    struct Girl : Person {
        virtual void hook() override { 
            std::cout << "Girl will leave the house.\n";
            location->hook(this);
            // ...
        }
        virtual void invoke_hook (Location* location) override { location->hook(this); }  // Double dispatch
    };
    
    struct Guy : Person {
        virtual void hook() override { 
            std::cout << "Guy will leave the house.\n";
            location->hook(this);
            // ...
        }
        virtual void invoke_hook (Location* location) override { location->hook(this); }  // Double dispatch
    };
    
    void House::hook (Person* person) {
        person->invoke_hook(this);  // Double dispatch
    }
    
    int main() {
        std::list<Person*> people = {new Girl, new Guy};
        for (Person* p : people)
            p->leave();  // Simple overloads will do the job here.
    
        House* house = new House;
        for (Person* p : people)
            house->hook(p);  // Double dispatch used.
    }
    

    输出:

    Girl will leave the house.
    Girl left the house.
    Guy will leave the house.
    Guy left the house.
    Girl left the house.
    Guy left the house.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多