責任の設計パターン

他のパターン説明を読んでください





問題



潜在的に多数のハンドラーを備えたシステムでイベント/リクエスト/メッセージのフローを処理するメカニズムを効果的かつコンパクトに実装します。



説明



イベント/ハンドラモデルは、さまざまな分野のソフトウェアシステムで広く使用されています。 基本的に、これはユーザーアクションによって生成されたイベントがインターフェイス要素によってさまざまな方法で処理されるグラフィカルユーザーインターフェイスです。 このようなモデルを頻繁に実装するWinAPIを忘れてはなりません。 ほとんどのソースでは、このモデルはイベントループと呼ばれます





一方では、すべてが非常に透明です。 メッセージには多くの種類があり、これらのメッセージには多くのハンドラがあります。 タスクは、ストリーム内の各メッセージを、特定のタイプの関連プロセッサーで処理することです。 簡単に言えば、メッセージタイプとハンドラーをリンクするための効果的なメカニズムが必要です。



ほとんどの場合、システム内に少数のハンドラーが固定されているため、if-then-else構造に基づいてこのメカニズムを実装するだけで十分です。 ただし、必ずしもそれほど単純ではありません。 まず、必要なハンドラーの数が事前に正確に常にわかっているわけではありません。 第二に、システムに新しいタイプのメッセージを追加すると、通常、新しいハンドラーが出現しますが、その導入はすでに非常に難しいタスクになっています。



このような問題を解決するために、「責任の連鎖」というテンプレートがあります。



テンプレートの考え方は、各ハンドラーが着信メッセージ(特定のタイプのメッセージのみなど)を処理するか、パイプライン内の次のハンドラーに処理を委任できる、ハンドラーの反復パイプラインを編成することです。 処理のさらなる変形とその後の送信が可能です。 同時に、特定のメッセージの処理を開始するために、クライアントはそれをパイプラインの最初のプロセッサに渡すだけで済みます。



実用例



おそらくテンプレートの最も明白な例-コンピューターネットワークを考えてみてください。 確かに-多数のハンドラー-ネットワークノード(コンピューター、サーバー、ルーター)および多数の種類のネットワーク要求。



単純化された架空のネットワークモデルには、ネットワーク、ルーター、フォワーダー、サーバーの4種類のプロセッサがあると仮定します。 そのため、サーバー処理の要求という1種類の要求しかありません。 ハンドラーの動作は次のとおりです。ネットワークは単にその環境でリクエストを送信し、ルーターはネットワーク間でリクエストを送信し、フォワーダーは特定のホストにリクエストを送信し、サーバーはリクエストを処理します。



ホストはプロセッサのパイプラインです。 要求は特定のメッセージです。 チェーンに沿って移動する要求は、各ノードによって処理(ルーティング、転送)され、渡されます。 最終的にサーバーによって処理されるまで。



クラス図



注目すべき主なポイントは、コンベア処理を整理する方法です。 この場合、次のアプローチが使用されます。 すべてのハンドラーは、パイプラインの次のハンドラーに処理責任を委任するための自身(後続)への参照を含む1つの抽象クラスRequestHandledを実装します。 handleRequest()メソッドの実装は、デフォルトでそのような委任を実装します。





C ++実装



//  #ifndef REQUEST_H #define REQUEST_H #include <string> using namespace std; class Request { private: protected: public: string requestString; Request(string requestString) : requestString(requestString) { } }; #endif //  #ifndef REQUEST_HANDLER_H #define REQUEST_HANDLER_H #include "Request.h" class RequestHandler { protected: RequestHandler *successor; public: RequestHandler(); RequestHandler(RequestHandler *successor) : successor(successor) { } virtual void handleRequest(const Request& request) { successor->handleRequest(request); } }; RequestHandler::RequestHandler() { } #endif //  #ifndef HOST_H #define HOST_H #include "RequestHandler.h" class Host : public RequestHandler { private: protected: public: Host(); Host(Host *host); }; Host::Host() { } Host::Host(Host *host) : RequestHandler((RequestHandler*)host) { } #endif //  #ifndef NETWORK_H #define NETWORK_H #include "RequestHandler.h" #include "Router.h" class Network : public RequestHandler { private: protected: public: Network(Host *host); }; Network::Network(Host *host) : RequestHandler((RequestHandler*)host) { } #endif //  #ifndef ROUTER_H #define ROUTER_H #include "Host.h" #include "Network.h" #include "RequestHandler.h" #include "Request.h" #include <cstdlib> #include <iostream> using namespace std; class Router : public Host { private: void route(Network *network, const Request& request) { if (network != NULL) { ((RequestHandler*)network)->handleRequest(request); } else { cout << "ER: Network is unreachable. Request with string " << request.requestString << " was lost" << endl; } } protected: public: Router(Network *network); virtual void handleRequest(const Request& request) { route((Network*) successor, request); } }; Router::Router(Network *network) { successor = (RequestHandler*) network; } #endif //  #ifndef SERVER_H #define SERVER_H #include "Host.h" #include "Request.h" #include "string" using namespace std; class Server : public Host { private: void showMessage(const string& msg) { cout << msg << endl; } protected: public: Server() : Host(NULL) { } virtual ~Server(); virtual void handleRequest(const Request& request) { string messageStr = "Request received with string: " + request.requestString; showMessage(messageStr); } }; #endif //  #ifndef FORWARDER_H #define FORWARDER_H #include "Host.h" #include "Request.h" class Forwarder : public Host { private: protected: public: Forwarder(Host *host) : Host(host) { } virtual ~Forwarder(); }; #endif //  #include <iostream> #include <cstdlib> using namespace std; #include "Server.h" #include "Router.h" #include "Forwarder.h" #include "Network.h" int main(int argc, char *argv[]) { Server *webServer = new Server(); Forwarder *fw1 = new Forwarder(webServer); Forwarder *fw2 = new Forwarder(fw1); Network *network = new Network(fw2); Router *router = new Router(network); const Request *req = new Request("correct request"); router->handleRequest(*req); Router *router1 = new Router(NULL); Forwarder *fw3 = new Forwarder(router1); Forwarder *fw4 = new Forwarder(fw3); Network *network2 = new Network(fw4); Router *router2 = new Router(network2); const Request *req1 = new Request("incorrect request"); router2->handleRequest(*req1); system("pause"); }
      
      







PS



気配りのある読者はこう言います-「ああ! 私はすでにこの男の記事を読んでいます!」 そうです、私はデザインパターンに関する一連の記事を続けることにしました。フィードバックをお待ちしています。



All Articles