CoR против простого if else и функциональных вызовов на основе матрицы, где цепочка зависит от запроса - PullRequest
0 голосов
/ 29 мая 2020

Scenario

Я использовал сопоставление обработчиков вместе с условной конструкцией if else для обработки цепочек, зависящих от запроса.

Request r(TYPE1, ACTIVE);
std::vector<TYPE, STATUS> mapping;
mapping[TYPE1][PENDING] = myHandlerA();
// ... and so on
mapping[r.type()][r.status()]();

void myHandlerA(Request& r) {
  if(condition4(r))
  Handler4(r);

  else if(condition5(r))
  Handler5(r);

  else if(condition6(r))
  Handler6(r);

  else if(condition7(r))
  Handler7()
}
  1. Как делать это с помощью CoR, когда цепочка зависит от запроса? Мой подход - хороший дизайн?
  2. Применимо ли этот случай к CoR? Может ли кто-нибудь предоставить фрагмент, если да.
  3. Как определить применимость CoR по сравнению с простым сопоставлением на основе if else?

1 Ответ

0 голосов
/ 29 мая 2020

Было бы легче ответить, увидев интерфейс обработчика CoR:

class BaseHandler {
public:
    void setNext(BaseHandler* next){ m_next = next; }
    void handle(Request r){
        handleImpl(r);
        if(m_next!=nullptr) {
            m_next->handle(r);
        }
    };
    virtual ~BaseHandler(){ if (m_next) delete m_next; }
protected:
    BaseHandler* m_next;
    virtual void handleImpl(Request r) = 0;
};

(изменен порядок ответов для более логичного вывода) 2. Ваш myHandlerA состоит из нескольких операторов if-else, поэтому используется только один из Handler4-Handler7. CoR предназначен для выполнения нескольких обработчиков в конкретном порядке. 1. (сначала прочтите описание, затем go для фрагментов) Вы можете создать фабричный метод для создания обработчика, подходящего для вашего запроса.

class Request {
    public:
    int type;
};

class Handler1: public BaseHandler{
    void handleImpl (Request r) override {
        cout << "Handler1" << endl;
    }
};

class Handler2: public BaseHandler{
    void handleImpl (Request r) override {
        cout << "Handler2" << endl;
    }
};

class MyFactory {
public:
    BaseHandler* getHandler(const Request& r){
        if (r.type==1){
            return new Handler1;
        }
        if (r.type==2){
            return new Handler2;
        }
    }
};

int main(){
    Request r;
    r.type=1;
    MyFactory myFactory;
    BaseHandler* handler = myFactory.getHandler(r);
    handler->handle(r);
    delete handler;
}

ИЛИ Вы можете создать обработчик CoR (см. Выше), который устанавливает свой m_next в соответствующий обработчик в зависимости от типа запроса. Таким образом, вы можете применить CoR в своем решении.

class RequestTypeHandler: public BaseHandler{
    void handleImpl (Request r) override {
        cout << "RequestTypeHandler" << endl;
        if (r.type==1){
            cout << "Select Handler1" << endl;
            m_next = new Handler1;
        }
        if (r.type==2){
            cout << "Select Handler2" << endl;
            m_next = new Handler2;
        }
    }
};

int main(){
    Request r;
    r.type=1;
    RequestTypeHandler handler;
    handler.handle(r);
}
Как сказано в ответе на 1., CoR посвящен скорее порядку обработчиков, а не одному, как в случае сопоставления.

Кроме того, я бы предложил отличную страницу с шаблонами дизайна : https://refactoring.guru

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...