@egorggegor

Почему не работает (Chain of Responsibilty)?

Ку
Реализовал паттерн цепочка обязанностей, но при тестировании выскакивает проблема с потоками, кто знает, как с этим разобраться?
(Проблема помечена в коде, тесты, на которых выявилась проблема в мэйне)
class Handler {
public:
    Handler(): next(nullptr) {};
    virtual ~Handler() {};
    virtual void HandleRequest(int data) {
        if (next) {
            this->next->HandleRequest(data);
        }
    }
    void SetNextHandler(Handler* next_handler) {  //Здесь вроде проблема
        if (next) {
            this->SetNextHandler(next_handler);
        } else {
            this->next = next_handler;
        }
    }
public:
    Handler* next;
};

class ConcreteHandler1 : public Handler {
public:
    void HandleRequest(int data) {
        //if can handle it do it
            //implementation of HadleRequest
        //else
        std::cout << "ConcreteHandler1" << std::endl;
        Handler::HandleRequest(data);
    }
};

class ConcreteHandler2 : public Handler {
public:
    void HandleRequest(int data) {
        //if can handle it do it
            //implementation of HadleRequest
        //else
        std::cout << "ConcreteHandler2" << std::endl;
        Handler::HandleRequest(data);
    }
};

int main(int argc, const char * argv[]) {
    Handler* handler = new Handler;
    int data;
    handler->SetNextHandler(new ConcreteHandler1());
    handler->SetNextHandler(new ConcreteHandler2());
    handler->HandleRequest(data);
    return 0;
}
  • Вопрос задан
  • 111 просмотров
Решения вопроса 1
@lorc
Подозреваю, что должно быть вот так:

void SetNextHandler(Handler* next_handler) {  
        if (next) {
            next->SetNextHandler(next_handler); // <- next, не this
        } else {
            this->next = next_handler;
        }
    }


Иначе у вас бесконечная рекурсия получится.

Но вообще, это не самый оптимальный алгоритм, ибо сложность добавления нового хендлера - O(N), хотя можно было бы сделать O(1), если не важен порядок вызова.

А еще, можно бы завести виртуальную функцию, которая будет занимать только хендлингом. Это сделает код более надежным и позволит избежать Handler::HandleRequest(data); в конце каждого хендлера.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы