Wzorce projektowe – Łańcuch Odpowiedzialności

 Lip, 09 - 2017   brak komentarzy   PHPWzorce Projektowe

wzorzez projektowy - łańcuch odpowiedzialności Łańcuch Odpowiedzialności to czynnościowy wzorzec projektowy, tworzący listę obiektów, które po kolei analizują żądanie i jeżeli potrafią je obsłużyć, to przystępują do procesu jego realizacji. W przeciwnym wypadku przekazują żądanie dalej, do kolejnego ogniwa w łańcuchu.

 

 

 

Łańcuch Odpowiedzialności (Chain of Responsibility) nazywany jest również łańcuchem zobowiązań, ponieważ jego głównym zadaniem  jest przekazanie zobowiązania obsługi żądania na kolejny element w łańcuchu. Łańcuch takich obiektów tworzy listę jednokierunkową, w której odpowiedzialność za przetworzone żądanie spada na najlepiej przygotowany do tego obiekt.

Struktura kodu i zastosowanie opisywanego tu wzorca jest bardzo proste, co pokazuje poniższy diagram klas UML. Łańcuch odpowiedzialności składa się z obiektów (ogniw), które kolejno sprawdzają czy są w stanie przetworzyć przekazane im żądanie. Jeżeli tak to realizują zadanie i zwracają wynik, natomiast jeżeli nie, to przekazują żądanie dalej, do kolejnego ogniwa w łańcuchu. Każde z ogniw powinno wskazywać na koleje, oczywiście oprócz ostatniego, który oprócz kodu przetwarzającego żądanie, powinien obsłużyć sytuację, w której żaden z obiektów nie był w stanie zrealizować zadania.

 

łańcuch odpowiedzialności - diagram klas UML

 

Przykład w języku PHP, opisany poniżej, przedstawia sposób i implementacji i użycia wzorca Łańcuch Odpowiedzialności. Zadaniem skryptu będzie wykonanie prostych operacji matematycznych na dwóch liczbach.

Jako pierwszą napiszemy prostą klasę, która będzie reprezentowała nasze żądanie do przetworzenia. Klasa posiada właściwości przechowujące liczby, na których będzie wykonywana operacja oraz rodzaj tej operacji.

Teraz przystąpmy do napisania struktury programu, opartego na omawianym wzorcu. W pierwszej kolejności będzie to abstrakcyjna klasa reprezentująca abstrakcyjne ogniwo łańcucha. Klasa ta będzie rozszerzana w dalszej części przez konkretne ogniwa. Zawiera ona referencje do kolejnego ogniwa oraz metodę ustawiającą to ogniwo. Posiada również abstrakcyjną funkcję realizującą przekazywane żądanie. Metoda ta będzie implementowana w kolejnych elementach łańcucha.

 

 

Przystąpmy do napisania poszczególnych ogniw wzorca. Będą to klasy realizujące poszczególne działania matematyczne – dodawanie, odejmowanie, mnożenie i dzielenie. Jak widać  na poniższych listingach poszczególne klasy implementują metodę obsługującą żądanie, w której najpierw sprawdzają, czy są w stanie to zrobić. Jeżeli tak zwracają wynik, jeżeli nie, to wywołują tę samą metodę w kolejnym elemencie łańcucha.

Mając tak napisany skrypt, zadaniem klienta jest odpowiednie przygotowanie łańcucha, tzn. ustawienie kolejnych jego elementów, a następnie wywołania odpowiedniej metody na pierwszym obiekcie. W przypadku, gdy klient źle zbuduje łańcuch może dojść do sytuacji, gdzie żądanie nie zostanie w ogóle obsłużone.

Bardzo często zdarza się, że klient nie ma pojęcia, które ogniwo łańcucha zrealizuje zlecone zadanie. Wynik działania powyższego testu jest jak najbardziej poprawny.

Zaletą stosowania wzorca łańcucha zobowiązań jest możliwość dynamicznego dodawania lub usuwania jego elementów. Ogniwa łańcucha są niezależne od siebie i nie muszą znać struktury łańcucha.

 

Powyższy przykład można pobrać tutaj: numbers-calc

Przykład na GitHub: https://github.com/molitorys/design-patterns/tree/master/src/ChainOfResponsibility/Numbers


Przeczytaj równierz


Dodaj komentarz

Twój adres email nie zostanie opublikowany.