Zabawne, to pytanie przypomniało mi dokładnie tę samą rozmowę z jednym z naszych inżynierów na temat biblioteki komunikacji, nad którą pracowałem.
Zamiast poleceń miałem klasy Request, a następnie miałem RequestHandlers. Projekt był bardzo podobny do tego, co opisujesz. Myślę, że część zamieszania, które masz, polega na tym, że widzisz angielskie słowo „polecenie” i od razu myślisz „czasownik, działanie ... itd.”.
Ale w tym projekcie myśl o Dowództwie (lub Żądaniu) jak o liście. Lub dla tych, którzy nie wiedzą, czym jest usługa pocztowa, pomyśl o e-mailu. Jest to po prostu treść oddzielona od sposobu, w jaki należy na nią postępować.
Dlaczego miałbyś to zrobić? W najprostszych przypadkach wzorzec poleceń nie ma żadnego powodu, a klasa mogłaby bezpośrednio wykonywać pracę. Jednak wykonanie odsprzęgania jak w twoim projekcie ma sens, jeśli twoje działanie / polecenie / prośba musi przebyć pewien dystans. Na przykład w poprzek gniazd lub potoków lub między domeną a infrastrukturą. A może w twojej architekturze twoje polecenia muszą być trwałe (np. Moduł obsługi poleceń może wykonać 1 polecenie na raz, z powodu niektórych zdarzeń systemowych, przybywa 200 poleceń i po pierwszych 40 procesach zostaje zamknięty). W takim przypadku, mając prostą klasę tylko do wyświetlania komunikatów, bardzo łatwo jest serializować tylko część komunikatu do JSON / XML / binary / cokolwiek i przekazywać ją w potoku, dopóki program obsługi poleceń nie będzie gotowy do przetworzenia.
Kolejną zaletą oddzielenia polecenia od CommandHandler jest to, że teraz masz opcję równoległej hierarchii dziedziczenia. Na przykład wszystkie Twoje polecenia mogą pochodzić z podstawowej klasy poleceń obsługującej serializację. A może masz 4 z 20 programów obsługi poleceń, które mają wiele podobieństw, teraz możesz czerpać je z podstawowej klasy programu obsługi programów. Jeśli miałbyś mieć obsługę danych i poleceń w jednej klasie, ten rodzaj relacji szybko wymknąłby się spod kontroli.
Innym przykładem oddzielania byłby, gdyby twoje polecenie wymagało bardzo niewielkiej ilości danych wejściowych (np. 2 liczb całkowitych i ciągu), ale jego logika obsługi była wystarczająco złożona, gdzie chciałbyś przechowywać dane w pośrednich zmiennych składowych. Jeśli ustawisz w kolejce 50 poleceń, nie chcesz przydzielać pamięci dla całej pamięci pośredniej, więc oddzielasz Command od CommandHandler. Teraz ustawiasz w kolejce 50 lekkich struktur danych, a bardziej złożone przechowywanie danych jest przydzielane tylko raz (lub N razy, jeśli masz N programów obsługi) przez CommandHandler, który przetwarza polecenia.