Wzorce projektowe: Chain of Responsibility

Wzorzec projektowy Chains of Responsibility prowadzi do utworzenia łańcucha obiektów, które analizują żadanie. Analiza przeprowadzana jest kolejno przez każdy z nich. Obiekt może zapewnić obsługę żądania lub przekazuje to żądanie dalej, lub to i to.

 1 public class Żądanie {
 2     private String title;
 3     private int value;
 4
 5     public Żądanie(String title, int value) {
 6         this.title = title;
 7         this.value = value;
 8     }
 9
10     public void print() {
11         System.out.println(title + " " + value);
12     }
13
14     public int getValue() {
15         return value;
16     }
17 }
18 
 1 public abstract class Łapacz {
 2     protected Łapacz następca;
 3
 4     public void setNastępca(Łapacz łapacz) {
 5         następca = łapacz;
 6     }
 7
 8     public abstract void łapŻądanie(Żądanie żądanie);
 9 }
10 
 1 public class ŁapaczNegatywny extends Łapacz {
 2
 3     public void łapŻądanie(Żądanie żądanie) {
 4         if (żądanie.getValue() < 0) {
 5             System.out.println("Łapacz negatywny łapie wartości mniejsze niż 0");
 6             żądanie.print();
 7         } else {
 8             if (następca != null)
 9                 następca.łapŻądanie(żądanie);
10         }
11     }
12 }
13 
 1 public class ŁapaczPozytywny extends Łapacz {
 2
 3     public void łapŻądanie(Żądanie żądanie) {
 4         if (żądanie.getValue() > 0) {
 5             System.out.println("Łapacz pozytywny łapie wartości większe niż 0");
 6             żądanie.print();
 7         } else {
 8             if (następca != null)
 9                 następca.łapŻądanie(żądanie);
10         }
11     }
12 }
 1 public class ŁapaczNeutralny extends Łapacz {
 2
 3     public void łapŻądanie(Żądanie żądanie) {
 4         if (żądanie.getValue() == 0) {
 5             System.out.println("Łapacz neutralny łapie wartości równe 0");
 6             żądanie.print();
 7         } else {
 8             if (następca != null)
 9                 następca.łapŻądanie(żądanie);
10         }
11     }
12 }
 1 public class TesterŁapaczy {
 2     public static void main(String[] args) {
 3         Łapacz łapacz1 = new ŁapaczNegatywny();
 4         Łapacz łapacz2 = new ŁapaczPozytywny();
 5         Łapacz łapacz3 = new ŁapaczNeutralny();
 6
 7         łapacz1.setNastępca(łapacz2);
 8         łapacz2.setNastępca(łapacz3);
 9
10         łapacz1.łapŻądanie(new Żądanie("Wartość negatywna ", -5));
11         łapacz1.łapŻądanie(new Żądanie("Wartość pozytywna ", 1));
12         łapacz1.łapŻądanie(new Żądanie("Wartość negatywna ", -1));
13         łapacz1.łapŻądanie(new Żądanie("Wartość negatywna ", -2));
14         łapacz1.łapŻądanie(new Żądanie("Wartość neutralna ", 0));
15         łapacz1.łapŻądanie(new Żądanie("Wartość negatywna ", -1));
16         łapacz1.łapŻądanie(new Żądanie("Wartość pozytywna ", 1));
17         łapacz1.łapŻądanie(new Żądanie("Wartość neutralna ", 0));
18         łapacz1.łapŻądanie(new Żądanie("Wartość pozytywna ", 1));
19         łapacz1.łapŻądanie(new Żądanie("Wartość negatywna ", -1));
20     }
21 }
22 

Diagram wzorca:

  • Wykop
  • Blip
  • Twitter
  • Facebook
  • DZone
  • Digg
  • Blinklist
  • Delicious
  • Evernote
  • LinkedIn
  • Google Bookmarks
  • Google Buzz
  • Google Reader
  • Share/Bookmark

Podobne wpisy:

2 Responses to “Wzorce projektowe: Chain of Responsibility”

  • Marioosh Says:

    Przy ostatnim projekcie uprościłem także klasę abstrakcyjną w setterze dla następnego Handlera. Otóż dodałem kod sprawdzający, czy Handler już istnieje i w przypadku gdy istnieje deleguję dodanie handlera do obecnego. Trochę to upraszcza sprawę, ponieważ, dodając do obojętnie którego Handlera następcę, ten ląduje na końcu kolejki. W przypadku, gdy kolejność jest nam obojętna jest dużym ułatwieniem.

  • Marioosh Says:

    Przyglądając się powyżej opisanemu wzorcowi, można zauważyć, że nie jest do końca zachowana zasada DRY. W każdym handlerze jest warunek sprawdzania, czy kolejny handler istnieje, a w przypadku gdy istnieje, metoda przechodzi dalej. Można to trochę ułatwić, przenosząc ten kod do abstrakcyjnej metody np. o nazwie ‘next(); metoda ‘łapŻądanie(), stanie się bardziej przejżysta, a w metodzie next() najpierw wywołamy łapŻądanie() a potem będzie kod sprawdzający. Pamiętać należy, żeby uruchomić łańcuch przez nową metodę.

Leave a Reply