Zagadka projektowa
Dziś będzie „lajcik”. Mam dla was zagadkę projektową. Załóżmy, że mamy zaprojektować klasę służącą do komunikacji z pewną usługą. Przy czym usługa ta odpowiada na zadane pytania w taki sposób, że odpowiedź może interesować wiele obiektów w ramach aplikacji. Przykładem może być tu proste wciśnięcie przycisku do którego możemy przypisać wiele listenerów. Generalnie zatem mówiąc mamy do czynienia ze wzorcem obserwatoraW. Jest on przydatny w wielu sytuacjach. Zadać by się mogło nawet niezbyt oczywistych. Na wzorcu tym można budować interfejsy SPI, ale też wykorzystać go do rozluźnienia powiązań pomiędzy obiektami. W tym ostatnim przypadku można zastąpić tradycyjne wiązanie jeden do jednego wiązaniem jeden do wielu dzięki czemu można z łatwością wpinać się w różne miejsca aplikacji bez potrzeby jej modyfikowania.
Przykładowo tradycyjna aplikacja wykorzystująca formularze CUD (Create, Uprade, Delete) ma zazwyczaj podpięty jeden obiekt DAO, który realizuje poszczególne operacje. Co jednak gdy chcemy informować różne usługi o zmianach zachodzących w obiekcie? Chociażby zapisywać logi do celów audytowych czy statystycznych? Oczywiście można wprowadzać zmiany. Ba! Można do tego użyć programowania aspektowego i wstawiać aspekty w runtime… można… można też od początku stosować kolekcje usług i później dodawać/usuwać pojedyncze elementy.
Jednak nie o tym chciałem, choć temat ciekawy.
Mamy sobie do zaimplementowania listener dla pewnej usługi. Wywołanie usługi może zakończyć się na dwa sposoby sukcesem albo porażką (LOL odkrywcze). Teraz zagadka.
Na poniższych listingach przedstawiono dwa interfejsy listenera pewnej usługi. Pytanie brzmi, który z nich jest lepszym rozwiązaniem i w jakiej sytuacji:
Listing 1. Listener „jednometodowy”
interface ServiceListener{
public void onEvent(Event e);
}
Klasa Event zawiera odpowiedź usługi w czystej postaci (strumień, String, prymityw).
Listing 2. Listener „wielemetodowy”
interface ServiceListener{
public void onSuccess(Response r);
public void onError(Error e);
}
Klasy Response i Error zawierają odpowiedź w czystej postaci, ale są wstępnie filtrowane tak by rozróżnić sukcesy i porażki.