SlideShare a Scribd company logo
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   PHP5. Obiekty,
                                         wzorce, narzêdzia
           KATALOG KSI¥¯EK
                                         Autor: Matt Zandstra
                      KATALOG ONLINE     T³umaczenie: Przemys³aw Szeremiota
                                         ISBN: 83-7361-868-6
       ZAMÓW DRUKOWANY KATALOG           Tytu³ orygina³u: PHP 5 Objects, Patterns, and Practice
                                         Format: B5, stron: 464

              TWÓJ KOSZYK                              Profesjonalne techniki programowania obiektowego w PHP5
                    DODAJ DO KOSZYKA         • Poznaj zasady projektowania i programowania obiektowego
                                             • Zastosuj wzorce projektowe podczas tworzenia aplikacji
                                             • Wykorzystaj narzêdzia wspomagaj¹ce pracê programisty PHP5
         CENNIK I INFORMACJE             Wraz z rosn¹c¹ popularno ci¹ jêzyka PHP zwiêksza siê równie¿ zakres jego
                                         zastosowañ. Za pomoc¹ PHP tworzy siê ju¿ nie tylko proste dynamiczne witryny WWW
                   ZAMÓW INFORMACJE      i fora dyskusyjne, ale równie¿ rozbudowane aplikacje sieciowe, wykorzystywane czêsto
                     O NOWO CIACH        w du¿ych przedsiêbiorstwach. Ju¿ w PHP4 zaimplementowano pewne mechanizmy
                                         u³atwiaj¹ce tworzenie rozbudowanych systemów, jednak dopiero PHP5 sta³ siê w pe³ni
                       ZAMÓW CENNIK      obiektowym jêzykiem programowania pozwalaj¹cym na korzystanie z wszystkich
                                         wynikaj¹cych z tego mo¿liwo ci.
                                         „PHP5. Obiekty, wzorce i narzêdzia” stanowi dok³adne omówienie wszystkich technik
                 CZYTELNIA               obiektowych w kontek cie zastosowania ich podczas tworzenia aplikacji w PHP5.
                                         Zawiera przegl¹d podstawowych i zaawansowanych cech PHP5 zwi¹zanych
          FRAGMENTY KSI¥¯EK ONLINE       z obiektowo ci¹. Przedstawia przyk³ady najczê ciej wykorzystywanych wzorców
                                         projektowych i zasady ich stosowania. Ksi¹¿ka opisuje równie¿ narzêdzia, które mog¹
                                         okazaæ siê bardzo przydatne podczas tworzenia rozbudowanych aplikacji, s³u¿¹ce
                                         do tworzenia dokumentacji i kontroli wersji plików.
                                             • Podstawowe pojêcia z dziedziny obiektowo ci
                                             • Obs³uga obiektów
                                             • Wyj¹tki i obs³uga b³êdów
                                             • Projektowanie obiektowe
                                             • Modelowanie obiektów w jêzyku UML
                                             • Wzorce projektowe
                                             • Stosowanie pakietu PEAR
Wydawnictwo Helion                           • Generowanie dokumentacji za pomoc¹ PHPDocumentor
ul. Chopina 6                                • Zarz¹dzanie wersjami plików w systemie CVS
44-100 Gliwice                               • Tworzenie pakietów instalacyjnych
tel. (32)230-98-63                              Przekonaj siê, jak potê¿nym narzêdziem jest najnowsza wersja jêzyka PHP
e-mail: helion@helion.pl
Spis treści
                O Autorze ......................................................................................... 9
                O Recenzencie Technicznym ........................................................... 10
                Przedmowa ..................................................................................... 11

Część I         Wprowadzenie ...............................................................13
Rozdział 1. PHP — projektowanie i zarządzanie ................................................. 15
                Problem .......................................................................................................................... 15
                PHP a inne języki programowania ................................................................................. 17
                O ksią ce ........................................................................................................................ 19
                Podsumowanie ............................................................................................................... 21

Część II        Obiekty .........................................................................23
Rozdział 2. PHP a obiekty ................................................................................ 25
                Nieoczekiwany sukces obiektów w PHP ........................................................................ 25
                Debata obiektowa — za czy przeciw? ............................................................................ 28
                Podsumowanie ............................................................................................................... 29
Rozdział 3. Obiektowy elementarz ..................................................................... 31
                Klasy i obiekty ............................................................................................................... 31
                Definiowanie składowych klasy ..................................................................................... 33
                Metody ........................................................................................................................... 36
                Typy argumentów metod ................................................................................................ 39
                Dziedziczenie ................................................................................................................. 44
                Podsumowanie ............................................................................................................... 58
Rozdział 4. Zaawansowana obsługa obiektów ................................................... 59
                Metody i składowe statyczne .......................................................................................... 59
                Składowe stałe ................................................................................................................ 63
                Klasy abstrakcyjne ......................................................................................................... 63
                Interfejsy ........................................................................................................................ 66
                Obsługa błędów .............................................................................................................. 68
                Klasy i metody finalne ................................................................................................... 75
                Przechwytywanie chybionych wywołań ......................................................................... 76
                Definiowanie destruktorów ............................................................................................ 80
6                                                                                           PHP5. Obiekty, wzorce, narzędzia


               Wykonywanie kopii obiektów ........................................................................................ 81
               Reprezentacja obiektu w ciągach znaków ...................................................................... 84
               Podsumowanie ............................................................................................................... 85
Rozdział 5. Narzędzia obiektowe ....................................................................... 87
               PHP a pakiety ................................................................................................................. 87
               Klasy i funkcje pomocnicze ........................................................................................... 92
               Reflection API ................................................................................................................ 99
               Podsumowanie ............................................................................................................. 110
Rozdział 6. Obiekty a projektowanie ............................................................... 111
               Jak rozumieć projektowanie? ....................................................................................... 111
               Programowanie obiektowe i proceduralne ................................................................... 112
               Zasięg klas .................................................................................................................... 117
               Polimorfizm .................................................................................................................. 119
               Hermetyzacja ................................................................................................................ 120
               Niewa ne jak ................................................................................................................ 122
               Cztery drogowskazy ..................................................................................................... 123
               Język UML ................................................................................................................... 124
               Podsumowanie ............................................................................................................. 133

Część III Wzorce .......................................................................135
Rozdział 7. Czym są wzorce projektowe? Do czego się przydają? ..................... 137
               Czym są wzorce projektowe? ....................................................................................... 137
               Wzorzec projektowy ..................................................................................................... 139
               Format wzorca według Bandy Czworga ....................................................................... 141
               Po co nam wzorce projektowe? .................................................................................... 142
               Wzorce projektowe a PHP ............................................................................................ 144
               Podsumowanie ............................................................................................................. 145
Rozdział 8. Wybrane prawidła wzorców ........................................................... 147
               Olśnienie wzorcami ...................................................................................................... 147
               Kompozycja i dziedziczenie ......................................................................................... 148
               Rozprzęganie ................................................................................................................ 153
               Kod ma u ywać interfejsów, nie implementacji ........................................................... 156
               Zmienne koncepcje ....................................................................................................... 157
               Nadmiar wzorców ........................................................................................................ 158
               Wzorce ......................................................................................................................... 159
               Podsumowanie ............................................................................................................. 160
Rozdział 9. Generowanie obiektów .................................................................. 161
               Generowanie obiektów — problemy i rozwiązania ...................................................... 161
               Wzorzec Singleton ....................................................................................................... 165
               Wzorzec Factory Method ............................................................................................. 169
               Wzorzec Abstract Factory ............................................................................................ 174
               Prototyp ........................................................................................................................ 179
               Ale to oszustwo! ......................................................................................................... 183
               Podsumowanie ............................................................................................................. 185
Rozdział 10. Relacje między obiektami ............................................................. 187
               Strukturalizacja klas pod kątem elastyczności obiektów .............................................. 187
               Wzorzec Composite ..................................................................................................... 188
               Wzorzec Decorator ....................................................................................................... 198
               Wzorzec Facade ........................................................................................................... 205
               Podsumowanie ............................................................................................................. 208
Spis treści                                                                                                                                       7


Rozdział 11. Reprezentacja i realizacja zadań ................................................... 209
                Wzorzec Interpreter ...................................................................................................... 209
                Wzorzec Strategy ......................................................................................................... 219
                Wzorzec Observer ........................................................................................................ 224
                Wzorzec Visitor ............................................................................................................ 231
                Wzorzec Command ...................................................................................................... 238
                Podsumowanie ............................................................................................................. 242
Rozdział 12. Wzorce korporacyjne .................................................................... 245
                Wprowadzenie .............................................................................................................. 245
                Małe oszustwo na samym początku ............................................................................. 248
                Warstwa prezentacji ..................................................................................................... 257
                Warstwa logiki biznesowej ........................................................................................... 287
                Warstwa danych ........................................................................................................... 295
                Podsumowanie ............................................................................................................. 317

Część IV Narzędzia ....................................................................319
Rozdział 13. Dobre (i złe) praktyki .................................................................... 321
                Nie tylko kod ................................................................................................................ 321
                Pukanie do otwartych drzwi ......................................................................................... 322
                Jak to zgrać? ................................................................................................................. 324
                Uskrzydlanie kodu ........................................................................................................ 325
                Dokumentacja ............................................................................................................... 326
                Testowanie ................................................................................................................... 328
                Podsumowanie ............................................................................................................. 336
Rozdział 14. PEAR ........................................................................................... 337
                Czym jest PEAR? ......................................................................................................... 338
                Instalowanie pakietu z repozytorium PEAR ................................................................. 338
                Korzystanie z pakietu PEAR ........................................................................................ 340
                Instalator pakietu PEAR ............................................................................................... 343
                Podsumowanie ............................................................................................................. 352
Rozdział 15. Generowanie dokumentacji — phpDocumentor .............................. 353
                Po co nam dokumentacja? ............................................................................................ 354
                Instalacja ...................................................................................................................... 355
                Generowanie dokumentacji .......................................................................................... 355
                Komentarze DocBlock ................................................................................................. 357
                Dokumentowanie klas .................................................................................................. 358
                Dokumentowanie plików .............................................................................................. 360
                Dokumentowanie składowych ...................................................................................... 360
                Dokumentowanie metod ............................................................................................... 361
                Tworzenie odnośników w dokumentacji ...................................................................... 363
                Podsumowanie ............................................................................................................. 365
Rozdział 16. Zarządzanie wersjami projektu z CVS ............................................ 367
                Po co nam CVS? .......................................................................................................... 367
                Skąd wziąć CVS? ......................................................................................................... 368
                Konfigurowanie repozytorium CVS ............................................................................. 369
                Rozpoczynamy projekt ................................................................................................. 372
                Aktualizacja i zatwierdzanie ......................................................................................... 374
                Dodawanie i usuwanie plików i katalogów .................................................................. 377
                Etykietowanie i eksportowanie wydania ........................................................................ 381
                Rozgałęzianie projektu ................................................................................................. 383
                Podsumowanie ............................................................................................................. 386
8                                                                                            PHP5. Obiekty, wzorce, narzędzia


Rozdział 17. Automatyzacja instalacji z Phing ................................................... 389
                Czym jest Phing? .......................................................................................................... 390
                Pobieranie i instalacja pakietu Phing ............................................................................ 391
                Plik kompilacji — build.xml ........................................................................................ 391
                Podsumowanie ............................................................................................................. 409

Część V         Konkluzje ....................................................................411
Rozdział 18. Obiekty, wzorce, narzędzia ............................................................ 413
                Obiekty ......................................................................................................................... 413
                Wzorce ......................................................................................................................... 417
                Narzędzia ...................................................................................................................... 420
                Podsumowanie ............................................................................................................. 424

Dodatki ......................................................................................425
Dodatek A Bibliografia ................................................................................... 427
                Ksią ki .......................................................................................................................... 427
                Publikacje ..................................................................................................................... 428
                Witryny WWW ............................................................................................................ 428
Dodatek B Prosty analizator leksykalny .......................................................... 429
                Skaner ........................................................................................................................... 429
                Analizator leksykalny ................................................................................................... 433
                Skorowidz ..................................................................................... 445
Rozdział 11.
Reprezentacja
i realizacja zadań
   W niniejszym rozdziale zaczniemy wreszcie działać i przyjrzymy się wzorcom projek-
   towym, które są pomocne w wykonywaniu zadań — od interpretacji minijęzyków po
   hermetyzacje algorytmów.

   Rozdział poświęcony będzie:
       Wzorcowi Interpreter — umo liwiającemu konstruowanie interpreterów
       minijęzyków nadające się do wbudowywania w aplikacje interfejsów
       skryptowych.
       Wzorcowi Strategy — zakładającemu identyfikowanie algorytmów stosowanych
       w systemie i ich hermetyzację do postaci osobnych, własnych typów.
       Wzorcowi Observer — tworzącemu zaczepy umo liwiające powiadamianie
       obiektów o zdarzeniach zachodzących w systemie.
       Wzorcowi Visitor — rozwiązującemu problem aplikacji operacji do wszystkich
       węzłów drzewa obiektów.
       Wzorcowi Command — obiektom poleceń przekazywanym pomiędzy
       częściami systemu.



Wzorzec Interpreter
   Języki programowania powstają i są rozwijane (przynajmniej z początku) w innych
   językach programowania. PHP został na przykład „spisany” w języku C. Nic więc nie
   stoi na przeszkodzie, abyśmy, posługując się PHP, zdefiniowali i wykorzystywali wła-
   sny język programowania. Oczywiście ka dy utworzony tak język będzie powolny i dość
   ograniczony, ale nie oznacza to, e będzie bezu yteczny — minijęzyki są całkiem przy-
   datne, co postaram się zademonstrować w tym rozdziale.
210                                                                     Część III ♦ Wzorce


      Tworząc interfejsy WWW (ale równie interfejsy wiersza poleceń) w języku PHP, da-
      jemy u ytkownikowi dostęp do pewnego zestawu funkcji. Zawsze w takim przypadku
      stajemy przed wyborem pomiędzy prostotą korzystania z interfejsu a zakresem mo -
      liwości oddawanych w ręce u ytkownika. Im więcej mo liwości dla u ytkownika, tym
      z reguły bardziej zło ony i rozdrobniony interfejs. Bardzo pomocne jest tu staranne
      zaprojektowanie interfejsu i rozpoznanie potrzeb u ytkowników — jeśli 90 procent
      z nich wykorzystuje jedynie 30 procent (tych samych) funkcji systemu, koszt udostęp-
      niania maksimum funkcjonalności mo e okazać się za wysoki w stosunku do efektów.
      Mo na wtedy rozwa yć uproszczenie systemu pod kątem „przeciętnego” u ytkownika.
      Ale co wtedy z owymi 10 procentami u ytkowników zaawansowanych korzystających
      z kompletu zaawansowanych funkcji systemu? Ich potrzeby mo na by zaspokoić ina-
      czej, na przykład udostępniając im wewnętrzny język programowania, w którym będą
      mogli odwoływać się do wszystkich funkcji systemu.

      Mamy ju co prawda pod ręką jeden język programowania. Chodzi o PHP. Moglibyśmy
      więc udostępnić go u ytkownikom i pozwolić im na tworzenie własnych skryptów:
         HQTOAKPRWV  RTKPV HKNGAIGVAEQPVGPVU
 GVERCUUYF  
        GXCN
 HQTOAKPRWV

      Jednak e takie rozszerzenie dostępności systemu wydaje się szaleństwem. Jeśli Czytel-
      nik nie jest przekonany co do nonsensowności tego pomysłu, powinien przypomnieć
      sobie o dwóch kwestiach: bezpieczeństwie i zło oności. Kwestia bezpieczeństwa jest
      dobrze ilustrowana w naszym przykładzie — umo liwiając u ytkownikom uzupełnia-
      nie systemu o ich własny kod w języku PHP, dajemy im w rzeczy samej pełny dostęp
      do serwera, na którym działa nasza aplikacja. Równie du ym problemem jest jednak
      zło oność — niezale nie od przejrzystości kodu aplikacji przeciętny u ytkownik będzie
      miał problemy z jej rozszerzeniem, zwłaszcza, jeśli ma z nią kontakt jednie za pośred-
      nictwem okna przeglądarki.

      Problemy te mo na wyeliminować, opracowując i udostępniając u ytkownikom własny
      minijęzyk. Mo na w nim połączyć elastyczność, zredukować mo liwość wyrządzania
      szkód przez u ytkowników i równocześnie zadbać o zwartość całości.

      Wyobraźmy sobie aplikację do tworzenia quizów. Autorzy mieliby układać pytania
      i ustalać reguły oznaczania poprawności odpowiedzi udzielanych przez uczestników
      quizu. Chodziłoby o to, eby quizy toczyły się bez interwencji operatora, choć część
      odpowiedzi miała by być wprowadzana przez uczestników w polach tekstowych.

      Oto przykładowe pytanie:
        +NW E QPMÎY NKE[ DCPFC GUKIP 2CVVGTPU!

      Poprawnymi odpowiedziami są „cztery” albo „4”. Mo emy utworzyć interfejs WWW,
      który pozwala twórcy quizu anga ować do rozpoznawania poprawnych odpowiedzi
      wyra enia regularne:
        @^EVGT[

      Jednak od twórców quizów rzadko wymaga się biegłości w konstruowaniu wyra eń
      regularnych — są oni cenieni raczej ze względu na wiedzę ogólną. Aby uprościć im
       ycie, mo na więc zaimplementować przyjaźniejszy mechanizm rozpoznawania po-
      prawnych odpowiedzi:
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                            211

            KPRWV GSWCNU  QT KPRWV GSWCNU EVGT[

        Mamy tu propozycję języka programowania obsługującego zmienne, operator o nazwie
        GSWCNU oraz operacje logiczne (QT czy CPF). Programiści uwielbiają nadawać nazwy
        swoim dziełom, nadajmy więc językowi jego miano — MarkLogic. Język miałby być
        łatwo rozszerzalny, bo ju oczyma wyobraźni widzimy postulaty zwiększenia jego
        mo liwości. Odłó my chwilowo na bok kwestię analizy leksykalnej, skupiając się na
        mechanizmie wykorzystania języka w czasie wykonania do generowania ocen odpo-
        wiedzi. Tu właśnie zastosowanie znajdzie wzorzec Interpreter.


Implementacja
        Nasz język składa się z wyra eń (to znaczy elementów, dla których da się obliczyć
        wartości). Z tabeli 11.1 wynika jasno, e nawet tak prosty język jak MarkLogic musi
        uwzględniać wiele elementów.
Tabela 11.1. Elementy gramatyki języka MarkLogic
 Opis                 Nazwa w notacji EBNF     Nazwa klasy             Przykład
 Zmienna              XCTKCDNG                 8CTKCDNG'ZRTGUUKQP       KPRWV
 Literał łańcuchowy   UVTKPI.KVGTCN           .KVGTCN'ZRTGUUKQP        EVGT[
 Logiczne i           CPF'ZRT                  $QQNGCP#PF'ZRTGUUKQP     KPRWV GSWCNU 
                                                                       CPF QVJGT GSWCNU 
 Logiczne lub         QT'ZRT                   $QQNGCP1T'ZRTGUUKQP      KPRWV GSWCNU 
                                                                       QT QVJGT GSWCNU 
 Test równości        GSWCNU'ZRT               'SWCNU'ZRTGUUKQP         KPRWV GSWCNU 

        W tabeli 11.1 mamy między innymi kolumnę nazw EBNF. Có to za nazwy? To nota-
        cja wykorzystywana do opisu gramatyki języka. EBNF to skrót od Extended Backu-
        sNaur Form (rozszerzona notacja Backusa-Naura). Notacja ta składa się z szeregu wierszy
        (zwanych regułami produkcyjnymi), w których znajduje się nazwa i opis przyjmujący
        postać odniesień do innych reguł produkcyjnych (ang. productions) i symboli końco-
        wych (ang. terminals), których nie da się ju wyrazić odwołaniami do kolejnych reguł
        produkcyjnych. Naszą gramatykę w notacji EBNF mo na by zapisać następująco:
           GZRT  QRGTCPF 
QT'ZRT ^ CPF'ZRT
QRGTCPF  
 
 GZRT  ^ UVTKPI.KVGTCN ^ XCTKCDNG  
GS'ZRT
QT'ZRT  QT QRGTCPF
           CPF'ZRT  CPF QRGTCPF
           GSWCNU'ZRT  GSWCNU QRGTCPF
           XCTKCDNG      YQTF

        Niektóre z symboli mają znaczenie specjalne (znane z notacji wyra eń regularnych):
        na przykład gwiazdka (
) oznacza zero lub więcej wystąpień, a pionowa kreska (^) to
        to samo co w języku naturalnym „lub”. Elementy grupujemy za pośrednictwem nawia-
        sów. W powy szym przykładzie wyra enie (GZRT) składa się z operandu (QRGTCPF),
        z którym występuje zero lub więcej wyra eń logicznej sumy (QT'ZRT) bądź logicznego
        iloczynu (CPF'ZRT). Operand mo e być wyra eniem ujętym w nawiasy, ciągiem ogra-
        niczonym znakami cudzysłowu (tej reguły produkcyjnej nie ma co prawda w powy -
        szym przykładzie) albo zmienną (XCTKCDNG). Jeśli przyzwyczaić się do ciągłego odsyła-
        nia od jednej reguły produkcyjnej do kolejnej, notacja EBNF staje się całkiem poręczna.
212                                                                        Część III ♦ Wzorce


        Na rysunku 11.1 mamy prezentację elementów gramatyki w postaci klas.

Rysunek 11.1.
Klasy
wzorca Interpreter
obsługujące
język MarkLogic




        Jak widać, klasa $QQNGCP#PF'ZRTGUUKQP i jej „rodzeństwo” dziedziczą po klasie 1RGTCVQ
        T'ZRTGUUKQP. Wszystkie te klasy realizują bowiem operacje na obiektach wyra eń
        (obiektach klasy 'ZRTGUUKQP). Klasy 8CTKCDNG'ZRTGUUKQP i .KVGTCN'ZRTGUUKQP operują
        wprost na wartościach.

        Wszystkie obiekty hierarchii 'ZRTGUUKQP implementują metodę KPVGTRTGV
 zdefiniowa-
        ną w abstrakcyjnej klasie bazowej hierarchii, czyli właśnie w klasie 'ZRTGUUKQP. Me-
        toda ta oczekuje przekazania w wywołaniu obiektu klasy %QPVGZV wykorzystywanego
        w roli wspólnego repozytorium danych. Ka dy obiekt klasy 'ZRTGUUKQP mo e składo-
        wać dane w obiekcie klasy %QPVGZV, który jest przekazywany pomiędzy obiektami
        hierarchii 'ZRTGUUKQP. Aby dało się w prosty sposób wyodrębniać dane z obiektu %QPVGZV,
        klasa bazowa 'ZRTGUUKQP implementuje metodę IGV-G[
 zwracającą unikalny uchwyt.
        Zobaczmy, jak całość działa w praktyce z implementacjami abstrakcji 'ZRTGUUKQP:
           CDUVTCEV ENCUU 'ZRTGUUKQP ]
               CDUVTCEV HWPEVKQP KPVGTRTGV
%QPVGZV EQPVGZV

                HWPEVKQP IGV-G[
 ]
                    TGVWTP 
UVTKPI VJKU
                _
           _

           ENCUU .KVGTCN'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ]
               RTKXCVG XCNWG

                HWPEVKQP AAEQPUVTWEV
 XCNWG ]
                     VJKU XCNWG  XCNWG
                _

                HWPEVKQP KPVGTRTGV
%QPVGZV EQPVGZV ]
                     EQPVGZV TGRNCEG
 VJKU VJKU XCNWG
                _
           _
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                            213


           ENCUU %QPVGZV ]
               RTKXCVG GZRTGUUKQPUVQTG  CTTC[

               HWPEVKQP TGRNCEG
'ZRTGUUKQP GZR XCNWG ]
                    VJKU GZRTGUUKQPUVQTG= GUR IGV-G[
?  XCNWG
               _

               HWPEVKQP NQQMWR
'ZRTGUUKQP GZR ]
                   TGVWTP VJKU GZRTGUUKQPUVQTG= GZR IGV-G[
?
               _
           _

            EQPVGZV  PGY %QPVGZV

            NKVGTCN  PGY .KVGTCN'ZRTGUUKQP
 EVGT[ 
            NKVGTCN KPVGTRTGV
 EQPVGZV
           RTKPV EQPVGZV NQQMWR
 NKVGTCN

        Zacznijmy od klasy %QPVGZV. Jak widać, jest ona w istocie jedynie fasadą tablicy aso-
        cjacyjnej reprezentowanej składową GZRTGUUKQPUVQTG i słu ącej do przechowywania
        danych. Metoda TGRNCEG
 klasy %QPVGZV przyjmuje na wejście obiekt klasy 'ZRTGUUKQP,
        który występuje w roli klucza tablicy asocjacyjnej, oraz wartość dowolnego typu lądu-
        jącą w tablicy asocjacyjnej w parze z przekazanym kluczem. Klasa udostępnia równie
        metodę NQQMWR
 umo liwiającą odczyt zapisanych w tablicy danych.

        Klasa 'ZRTGUUKQP definiuje abstrakcyjną metodę KPVGTRTGV
 i konkretną metodę
        IGV-G[
, która na podstawie bie ącego obiektu ( VJKU) generuje unikalną w obrębie
        hierarchii etykietę. Etykieta powstaje w wyniku rzutowania wartości VJKU na typ UVTKPI.
        Domyślny wynik konwersji obiektu na kontekst ciągu znaków to ciąg zawierający zna-
        kową reprezentację identyfikatora obiektu.
           ENCUU 2TKPV/G ]_
            VGUV  PGY 2TKPV/G

           RTKPV VGUV 

            wydruk:
            1DLGEV KF 

        Metoda IGV-G[
 czyni z tej cechy języka narzędzie generowania klucza do tabeli aso-
        cjacyjnej. Metoda ta jest wykorzystywana w kontekście wywołań %QPVGZVNQQMWR

        i %QPVGZVTGRNCEG
, konwertując argumenty typu 'ZRTGUUKQP na ich reprezentację
        znakową.

           Rzutowanie obiektów na ciągi na potrzeby tablic asocjacyjnych jest użyteczne,
           ale nie zawsze bezpieczne. W czasie pisania tej książki język PHP5 zawsze przy
           okazji takiego rzutowania generował ciąg z identyfikatorem obiektu. Zdaje się jed-
           nak, że docelowo konwersja ta ma uwzględniać implementację metody specjalnej
           AAVQ5VTKPI
. Oparcie wyniku konwersji na wywołaniu tej metody oznaczać będzie
           unieważnienie gwarancji wygenerowania unikalnego ciągu. Gwarancję tę będzie
           można przywrócić, jawnie implementując w klasie bazowej wykorzystywanej hierarchii
           metodę AAVQ5VTKPI
 jako metodę finalną, uniemożliwiając jej przesłanianie w kla-
           sach pochodnych:
               HKPCN HWPEVKQP AAVQ5VTKPI
 ]
                   TGVWTP 
UVTKPI VJKU
               _
214                                                                    Część III ♦ Wzorce


      Klasa .KVGTCN'ZRTGUUKQP definiuje konstruktor przyjmujący wartość dowolnego ty-
      pu zapisywaną w składowej XCNWG. Metoda KPVGTRTGV
 klasy wymaga zaś przekaza-
      nia obiektu klasy %QPVGZV. Jej implementacja sprowadza się do wywołania metody
      %QPVGZVTGRNCEG
 z przekazaniem w wywołaniu wartości zwracanej przez metodę
      IGV-G[
 i wartością składowej XCNWG. Schemat taki będziemy obserwować w pozo-
      stałych klasach wyra eń. Metoda KPVGTRTGV
 zawsze wypisuje wyniki swojego dzia-
      łania za pośrednictwem obiektu %QPVGZV.

      W prezentowanym kodzie nie zabrakło przykładowego kodu u ytkującego klasy kon-
      kretyzującego obiekty klas %QPVGZV i .KVGTCN'ZRTGUUKQP (z wartością „cztery”), a na-
      stępnie przekazującego obiekt %QPVGZV do wywołania .KVGTCN'ZRTGUUKQPKPVGTRTGV
.
      Metoda ta zapisuje parę klucz-wartość w obiekcie %QPVGZV, z którego mo na ją później
      wyodrębnić wywołaniem NQQMWR
.

      Zdefiniujmy pozostałe klasy symboli końcowych naszej gramatyki. Klasa 8CTKC
      DNG'ZRTGUUKQP jest ju nieco bardziej zło ona:
        ENCUU 8CTKCDNG'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ]
            RTKXCVG PCOG
            RTKXCVG XCN

              HWPEVKQP AAEQPUVTWEV
 PCOG XCNPWNN ]
                   VJKU PCOG  PCOG
                   VJKU XCN  XCN
              _

              HWPEVKQP KPVGTRTGV
%QPVGZV EQPVGZV ]
                  KH 
 KUAPWNN
 VJKU XCN ]
                       EQPVGZV TGRNCEG
 VJKU VJKU XCN
                       VJKU XCN  PWNN
                  _
              _

              HWPEVKQP UGV8CNWG
 XCNWG ]
                   VJKU XCN  XCNWG
              _

               HWPEVKQP IGV-G[
 ]
                   TGVWTP VJKU PCOG
               _
        _

         EQPVGZV  PGY %QPVGZV

         O[XCT  PGY 8CTKCDNG'ZRTGUUKQP
 KPRWV  EVGT[ 
         O[XCT KPVGTRTGV
 EQPVGZV
        RTKPV EQPVGZV NQQMWR
 O[XCT
         wydruk:
         EVGT[

         PGYXCT  PGY 8CTKCDNG'ZRTGUUKQP
 KPRWV 
         PGYXCT KPVGTRTGV
 EQPVGZV
        RTKPV EQPVGZV NQQMWR
 PGYXCT
         wydruk:
         EVGT[

            O[XCT UGV8CNWG
 RKúè
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                           215

            O[XCT KPVGTRTGV
 EQPVGZV
           RTKPV EQPVGZV NQQMWR
 O[XCT
            wydruk:
            RKúè

           RTKPV EQPVGZV NQQMWR
 PGYXCT
            wydruk:
            RKúè

        Klasa 8CTKCDNG'ZRTGUUKQP przyjmuje przy konstrukcji parę wartości: nazwę zmiennej
        i jej wartość. Udostępnia te metodę UGV8CNWG
, aby u ytkownicy mogli przypisywać
        do zmiennych nowe wartości.

        Metoda KPVGTRTGV
 sprawdza przede wszystkim, czy składowa XCN obiektu ma war-
        tość niepustą. Jeśli tak, wartość ta jest zapisywana w kontekście, po czym do składowej
         XCN przypisywana jest wartość pusta, na wypadek, gdyby metoda KPVGTRTGV
 została
        ponownie wywołana po tym, jak inny egzemplarz 8CTKCDNG'ZRTGUUKQP o tej samej na-
        zwie zmienił wartość zapisaną w kontekście. W rozszerzeniach języka trzeba by prze-
        widzieć operowanie na obiektach 'ZRTGUUKQP, tak aby zmienna mogła zawierać wyniki
        testów i operacji. Na razie jednak taka implementacja 8CTKCDNG'ZRTGUUKQP jest wystar-
        czająca. Zauwa my, e przesłoniliśmy w niej implementację IGV-G[
, tak aby wartość
        klucza konstytuowana była nie identyfikatorem egzemplarza klasy, a ciągiem zapisa-
        nym w składowej PCOG.

        Wyra enia operatorów w naszym języku ka dorazowo operują na dwóch obiektach
        'ZRTGUUKQP (obsługujemy bowiem wyłącznie operatory dwuargumentowe). Zasadne jest
        więc wyprowadzenie ich ze wspólnej klasy bazowej. Oto klasa 1RGTCVQT'ZRTGUUKQP:
           CDUVTCEV ENCUU QRGTCVQT'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ]
               RTQVGEVGF NAQR
               RTQVGEVGF TAQR

               HWPEVKQP AAEQPUVTWEV
'ZRTGUUKQP NAQR 'ZRTGUUKQP TAQR ]
                    VJKU NAQR  NAQR
                    VJKU TAQR  TAQR
               _

               HWPEVKQP KPVGTRTGV
%QPVGZV EQPVGZV ]
                    VJKU NAQR KPVGTRTGV
 EQPVGZV
                    VJKU TAQR KPVGTRTGV
 EQPVGZV
                    TGUWNVAN  EQPVGZV NQQMWR
 VJKU NAQR
                    TGUWNVAT  EQPVGZV NQQMWR
 VJKU TAQR
                    VJKU FQ1RGTCVKQP
 EQPVGZV TGUWNVAN TGUWNVAT
               _

               RTQVGEVGF CDUVTCEV HWPEVKQP FQ1RGTCVKQP
%QPVGZV EQPVGZV
                                                        TGUWNVAN
                                                        TGUWNVAT
           _

        Klasa 1RGTCVQT'ZRTGUUKQP to klasa abstrakcyjna. Implementuje co prawda metodę
        KPVGTRTGV
, ale definiuje równie abstrakcyjną metodę FQ+PVGTRTGV
.

        Konstruktor oczekuje przekazania dwóch obiektów klasy 'ZRTGUUKQP: NAQR i TAQR, do
        których referencje zapisywane są w zabezpieczonych składowych obiektu.
216                                                                     Część III ♦ Wzorce


      Implementacja metody KPVGTRTGV
 rozpoczyna się od wywołania KPVGTRTGV
 na
      rzecz obu operandów (jeśli pamiętasz poprzedni rozdział, zauwa ysz tu zapewne za-
      stosowanie wzorca Composite). Po ewaluacji operandów metoda KPVGTRTGV
 musi
      pozyskać zwracane przez nie wartości. Odwołuje się do niech za pośrednictwem me-
      tody %QPVGZVNQQMWR
 wywoływanej dla obu składowych. Dalej następuje wywołanie
      FQ+PVGTRTGV
, o którego wyniku decyduje jednak implementacja w klasach pochodnych.

      Spójrzmy na jej implementację w klasie 'SWCNU'ZRTGUUKQP, porównującej dwa obiekty
      klasy 'ZRTGUUKQP:
        ENCUU 'SWCNU'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ]
            RTQVGEVGF HWPEVKQP FQ1RGTCVKQP
%QPVGZV EQPVGZV TGUWNVAN TGUWNVAT ]
                 EQPVGZV TGRNCEG
 VJKU TGUWNVAN  TGUWNVAT
            _
        _

      Klasa 'SWCNU'ZRTGUUKQP implementuje jedynie metodę FQ1RGTCVKQP
, w ramach której
      porównuje wartości operandów przekazanych z metody KPVGTRTGV
 klasy nadrzędnej,
      a wynik porównania umieszcza w przekazanym obiekcie %QPVGZV.

      Implementację klas wyra eń wieńczą klasy wyra eń logicznych — $QQNGCP1T'ZRTGUUKQP
      i $QQNGCP#PF'ZRTGUUKQP:
        ENCUU $QQNGCP1T'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ]
            RTQVGEVGF HWPEVKQP FQ1RGTCVKQP
%QPVGZV TGUWNVAN TGUWNVAT ]
                 EQPVGZV TGRNCEG
 VJKU TGUWNVAN ^^ TGUWNVAT
            _
        _

        ENCUU $QQNGCP#PF'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ]
            RTQVGEVGF HWPEVKQP FQ1RGTCVKQP
%QPVGZV TGUWNVAN TGUWNVAT ]
                 EQPVGZV TGRNCEG
 VJKU TGUWNVAN      TGUWNVAT
            _
        _

      Zamiast sprawdzania równości aplikujemy tu operatory operacji logicznej sumy
      (w $QQNGCP1T'ZRTGUUKQP) bądź logicznego iloczynu ($QQNGCP#PF'ZRTGUUKQP). Wynik
      operacji jest przekazywany do metody %QPVGZVTGRNCEG
.

      Mamy ju bazę kodu wystarczającą do wykonania prezentowanego wcześniej fragmentu
      kodu naszego minijęzyka. Oto on:
         KPRWV GSWCNU  QT KPRWV GSWCNU EVGT[

      Powy sze wyra enie mo emy odwzorować w hierarchii 'ZRTGUUKQP w sposób nastę-
      pujący:
         EQPVGZV  PGY %QPVGZV

         KPRWV  PGY 8CTKCDNG'ZRTGUUKQP
 KPRWV 
         UVCVGOGPV  PGY $QQNGCP1T'ZRTGUUKQP

            PGY 'SWCNU'ZRTGUUKQP
 KPRWV PGY .KVGTCN'ZRTGUUKQP
 EVGT[ 
            PGY 'SWCNU'ZRTGUUKQP
 KPRWV PGY .KVGTCN'ZRTGUUKQP
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                           217


        Konkretyzujemy tu zmienną o nazwie KPRWV, ale wstrzymujemy się z przypisaniem jej
        wartości. Następnie tworzymy obiekt wyra enia sumy logicznej $QQNGCP'ZRTGUUKQP
        operującego na wynikach dwóch porównań realizowanych obiektami 'SWCNU'ZRTGUUKQP.
        W pierwszym porównaniu uczestniczą: obiekt wyra enia wartości (8CNWG'ZRTGUUKQP)
        przechowywanej w KPRWV z obiektem ciągu znaków (.KVGTCN'ZRTGUUKQP) zawierają-
        cym ciąg „cztery”; w drugim porównywany jest ten sam obiekt wartości KPRWV z cią-
        giem znaków „4”.

        Po takim rozpracowaniu wyra enia z przykładowego wiersza kodu mo emy przystąpić
        do obliczenia wartości zmiennej KPRWV i uruchomienia mechanizmu oceny:
           HQTGCEJ 
CTTC[
 EVGT[      CU XCN ]
                KPRWV UGV8CNWG
 XCN
               RTKPV XCNP 
                UVCVGOGPV KPVGTRTGV
 EQPVGZV
               KH 
 EQPVGZV NQQMWR
 UVCVGOGPV ]
                   RTKPV PCMQOKVC QFRQYKGF PP 
               _ GNUG ]
                   RTKPV Q Q NGL CYMKPP 
               _
           _

        Mamy tu trzykrotne uruchomienie tego samego kodu, dla trzech ró nych wartości
        zmiennej wejściowej. Za pierwszym razem ustawiamy tymczasową zmienną XCN na
        „cztery”, przypisując ją następnie do obiektu 8CTKCDNG'ZRTGUUKQP za pośrednictwem
        metody UGV8CNWG
. Dalej wywołujemy metodę KPVGTRTGV
 na rzecz szczytowego
        obiektu 'ZRTGUUKQP (obiektu $QQNGCP1T'ZRTGUUKQP zawierającego referencję do pozo-
        stałych obiektów wyra eń uczestniczących w instrukcji). Spójrzmy na sposób realiza-
        cji tego wywołania:
             Obiekt UVCVGOGPV wywołuje metodę KPVGRTGV
 na rzecz składowej NAQR
             (pierwszego obiektu klasy 'SWCNU'ZRTGUUKQP).
             Pierwszy z obiektów 'SWCNU'ZRTGUUKQP wywołuje z kolei metodę KPVGTRTGV

             na rzecz swojej składowej NAQR (referencji do obiektu 8CTKCDNG'ZRTGUUKQP
             przechowującego wartość „cztery”).
             Obiekt 8CTKCDNG'ZRTGUUKQP zapisuje swoją bie ącą wartość do wskazanego
             obiektu klasy %QPVGZV (wywołaniem %QPVGZVTGRNCEG
).
             Pierwszy z obiektów 'SWCNU'ZRTGUUKQP wywołuje metodę KPVGTRTGV

             na rzecz swojej składowej TAQR (referencji do obiektu .KVGTCN'ZRTGUUKQP
             inicjowanego wartością „cztery”).
             Obiekt .KVGTCN'ZRTGUUKQP rejestruje właściwą dla siebie parę klucz-wartość
             w obiekcie kontekstu.
             Pierwszy z obiektów 'SWCNU'ZRTGUUKQP odczytuje wartości NAQR („cztery”)
             i TAQR („cztery”) z obiektu kontekstu.
             Pierwszy z obiektów 'SWCNU'ZRTGUUKQP porównuje odczytane w poprzednim
             kroku wartości i rejestruje wynik porównania (VTWG) wraz z właściwym sobie
             kluczem w obiekcie kontekstu.
218                                                                       Część III ♦ Wzorce


           Po powrocie w górę drzewa obiektów następuje wywołanie metody
           KPVGTRTGV
 na rzecz składowej TAQR obiektu UVCVGOGPV. Wartość tego
           wywołania (tym razem HCNUG) obliczana jest identycznie jak dla pierwszego
           obiektu NAQR.
           Obiekt UVCVGOGPV odczytuje wartości swoich operandów z obiektu kontekstu
           i porównuje je za pośrednictwem operatora ^^. Suma logiczna wartości VTWG
           i HCNUG daje VTWG i taka wartość jest ostatecznie składowana w obiekcie kontekstu.

      Cały ten proces to zaledwie pierwsza iteracja pętli. Oto wynik wykonania wszystkich
      trzech przebiegów:
        EVGT[
        PCMQOKVC QFRQYKGF

        
        PCMQOKVC QFRQYKGF

        
        Q Q NGL CYMK

      Być mo e zrozumienie tego, co dzieje się w powy szym kodzie, wymagać będzie kil-
      kukrotnej lektury opisu — znów mamy bowiem do czynienia z pomieszaniem pomiędzy
      drzewami klas a hierarchiami obiektów. Klasy wyra eń tworzą hierarchię dziedzicze-
      nia 'ZRTGUUKQP, ale równocześnie obiekty tych klas są w czasie wykonania formowane
      w strukturę drzewiastą. Nale y jednak pamiętać o rozró nieniu obu hierarchii.

      Kompletny diagram klas dla tego przykładu prezentowany jest na rysunku 11.2.


Ciemne strony wzorca Interpreter
      Po uło eniu rdzenia hierarchii klas wzorca Interpreter jego rozbudowa jest ju dość pro-
      sta, odbywa się jednak przez tworzenie coraz to nowych klas. Z tego względu wzorzec
      Interpreter najlepiej stosować do implementacji języków stosukowo uproszczonych.
      W obliczu potrzeby pełnoprawnego języka programowania nale ałoby raczej skorzy-
      stać z gotowych narzędzi przeznaczonych do analizy leksykalnej i implementacji wła-
      snej gramatyki.

      Dalej, klasy wzorca Interpreter często realizują bardzo podobne zadania, warto więc
      pilnować, aby nie dochodziło w nich do niepotrzebnego powielania kodu.

      Wiele osób, przymierzając się do pierwszego w swoim wykonaniu wdro enia wzorca
      Interpreter, rozczarowuje się odkryciem faktu, e wzorzec ten nie obejmuje analizy
      leksykalnej. Oznacza to, e nie wystarczy on do implementacji gotowego mechanizmu
      skryptowego rozszerzania aplikacji. Przykładowa implementacja analizy leksykalnej
      mocno uproszczonego języka prezentowana jest w dodatku B.
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                           219




Rysunek 11.2. Wdro enie wzorca Interpreter




Wzorzec Strategy
        Klasy często obcią ane są nadmierną liczbą zadań. To zrozumiałe: niemal zawsze two-
        rzymy je z myślą o kilku podstawowych funkcjach. W trakcie kodowania okazuje się,
         e niektóre z tych funkcji trzeba zmieniać w zale ności od okoliczności. Oznacza to
        konieczność podziału klasy na podklasy. I zanim się ktokolwiek obejrzy, projekt zostaje
        rozdarty przeciwnymi nurtami.


Problem
        Poniewa zdołaliśmy ostatnio opracować implementację miniaturowego języka oceny,
        trzymajmy się przykładu z quizami. Quizy nie mogą się obejść bez pytań, skonstruujemy
        więc klasę 3WGUVKQP (pytanie) i wyposa ymy ją w metodę oceny — OCTM
. Wszystko
        w porządku, dopóki nie pojawi się potrzeba obsługiwania ró nych mechanizmów
        oceniania.

        Załó my, e mamy zaimplementować ocenę wedle języka MarkLogic, ocenę na pod-
        stawie prostego dopasowania odpowiedzi i ocenę z dopasowaniem przy u yciu wyra eń
        regularnych. W pierwszym podejściu moglibyśmy zró nicować projekt pod kątem tych
        mechanizmów oceny, jak na rysunku 11.3.
220                                                                         Część III ♦ Wzorce


Rysunek 11.3.
Definiowanie
klas pochodnych
wedle strategii oceny




         Całość będzie się sprawdzać dopóty, dopóki ocena pozostanie jedynym zmiennym
         aspektem hierarchii. Wyobraźmy sobie jednak, e za ądano od nas dodatkowo obsłu-
         gi ró nego rodzaju pytań: czysto tekstowych i opartych na materiale audiowizualnym.
         Powstaje problem uwzględnienia dwóch kierunków zmian w jednym drzewie dziedzi-
         czenia — patrz rysunek 11.4.




Rysunek 11.4. Wyró nianie klas pochodnych według dwóch kryteriów podziału

         Nie tylko doszło do podwojenia (niemal) liczby klas w hierarchii, ale i do powielenia
         kodu. Nasza logika oceniania jest bowiem powielona w obu podgałęziach hierarchii
         dziedziczenia.

         Jeśli kiedykolwiek staniesz w obliczu powielania algorytmu w równoległych gałęziach
         hierarchii dziedziczenia (powielania tak przez wydzielanie klas pochodnych, jak i roz-
         budowywanie instrukcji warunkowych), powinieneś rozwa yć wyodrębnienie algorytmu
         do jego własnego typu.
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                        221


Implementacja
        Wzorzec Strategy (strategia), podobnie jak cała gama najlepszych wzorców, łączy
        prostotę z wielkimi mo liwościami. Kiedy klasy muszą obsługiwać wielorakie imple-
        mentacje interfejsu (u nas są to wielorakie mechanizmy oceny), wzorzec ten zakłada
        zaniechanie rozbudowywania oryginalnej hierarchii klas, zalecając wyodrębnienie
        owych implementacji do osobnego typu.

        Odnosząc to do naszego przykładu, powiedzielibyśmy, e najlepiej byłoby wyod-
        rębnić osobny typ mechanizmu oceny — /CTMGT. Nową strukturę projektu ilustruje ry-
        sunek 11.5.

Rysunek 11.5.
Wyodrębnienie
algorytmów
do osobnego typu




        To kolejny znakomity przykład wdro enia jednej z podstawowych zasad projektowych
        promowanych przez Bandę Czworga (i nie tylko), a mówiącej o wy szości kompozy-
        cji nad dziedziczeniem. Definiując i hermetyzując algorytmy oceny, redukujemy licz-
        bę pochodnych w hierarchii dziedziczenia i zwiększamy równocześnie elastyczność
        systemu. Mo emy go bowiem w dogodnych momentach uzupełniać o następne stra-
        tegie oceny bez konieczności wprowadzania jakichkolwiek zmian w klasach hierarchii
        3WGUVKQP. Wszystkie klasy tej hierarchii mają do swojej dyspozycji egzemplarz klasy
        /CTMGT, a interfejs klas udostępnia metodę oceny OCTM
. Szczegóły implementacji są
        dla wywołującego tę metodę zupełnie nieistotne.

        Oto hierarchia 3WGUVKQP wyra ona kodem źródłowym:
           CDUVTCEV ENCUU 3WGUVKQP ]
               RTQVGEVGF RTQORV
               RTQVGEVGF OCTMGT

               HWPEVKQP AAEQPUVTWEV
 RTQORV /CTMGT OCTMGT ]
                    VJKU OCTMGT  OCTMGT
                    VJKU RTQORV  RTQORV
               _

               HWPEVKQP OCTM
 TGURQPUG ]
222                                                                                   Część III ♦ Wzorce


                 TGVWTP VJKU OCTMGT OCTM
 TGURQPUG
            _
        _

        ENCUU 6GZV3WGUVKQP GZVGPFU 3WGUVKQP ]
             operacje charakterystyczne dla prezentacji pytań w formie tekstowej…
        _

        ENCUU #83WGUVKQP GZVGPFU 3WGUVKQP ]
             operacje charakterystyczne dla prezentacji pytania z materiałem audiowizualnym…
        _

      Szczegóły implementacyjne rozró niające klasy 6GZV3WGUVKQP i #83WGUVKQP pozosta-
      wiłem wyobraźni Czytelnika. Najwa niejsze z naszego punktu widzenia funkcje tych
      klas zdefiniowane zostały bowiem w klasie bazowej 3WGUVKQP, która ponadto przecho-
      wuje w składowej OCTMGT obiekt oceny (obiekt klasy /CTMGT). Kiedy następuje wywo-
      łanie metody 3WGUVKQPOCTM
 z argumentem reprezentującym odpowiedź uczestnika
      quizu, realizacja wywołania w klasie 3WGUVKQP polega na oddelegowaniu wywołania
      do odpowiedniej metody obiektu /CTMGT.

      Zdefiniujmy klasę obiektów /CTMGT:
        CDUVTCEV ENCUU /CTMGT ]
            RTQVGEVGF VGUV

            HWPEVKQP AAEQPUVTWEV
 VGUV ]
                 VJKU VGUV  VGUV
            _

            CDUVTCEV HWPEVKQP OCTM
 TGURQPUG
        _

        ENCUU /CTM.QIKE/CTMGT GZVGPFU /CTMGT ]
            RTKXCVG GPIKPG
            HWPEVKQP AAEQPUVTWEV
 VGUV
                RCTGPVEQPUVTWEV
 VGUV
                 $this-engine = new MarkParse($test);
            _

            HWPEVKQP OCTM
 TGURQPUG ]
                 return $this-engine-evaluate($response);
                 na razie działa na niby:
                TGVWTP VTWG
            _
        _

        ENCUU /CVEJ/CTMGT GZVGPFU /CTMGT ]
            HWPEVKQP OCTM
 TGURQPUG ]
                TGVWTP 
 VJKU VGUV  TGURQPUG
            _
        _

        ENCUU 4GIGZR/CTMGT GZVGPFU /CTMGT ]
            HWPEVKQP OCTM
 TGURQPUG ]
                TGVWTP 
RTGIAOCVEJ
 VJKU VGUV TGURQPUG
            _
        _
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                            223


        W implementacji klas hierarchii /CTMGT niewiele jest elementów zaskakujących —
        w rzeczy samej niewiele z nich wymaga w ogóle jakiegokolwiek komentarza. Zauwa -
        my jedynie, e obiekty klasy /CTM.QIKE/CTMGT są przystosowane do korzystania z ana-
        lizatora leksykalnego, którego kod jest prezentowany w dodatku B. Jednak na potrzeby
        tego przykładu mo emy ten aspekt klasy pominąć, więc metoda /CTM.QIKE/CTMGTOCTM

        realizuje na razie ocenę „na pół gwizdka”, zwracając za ka dym razem VTWG. Najwa -
        niejsza w tej hierarchii jest definiowana nią struktura, nie zaś szczegóły implementacji
        poszczególnych strategii ocen. Struktura ta ma zaś umo liwiać przełączanie mechani-
        zmu oceny pomiędzy obiektami hierarchii /CTMGT bez uszczerbku dla klasy 3WGUVKQP,
        która się do tego mechanizmu odwołuje.

        Wcią pozostaje oczywiście kwestia podjęcia decyzji co do zastosowania jednego
        z konkretnych obiektów hierarchii /CTMGT. Problem ten rozwiązuje się w praktyce na
        dwa sposoby. Pierwszy polega na wyborze strategii oceny na etapie układania quizu
        przez jego autora, a wybór sprowadza się do zaznaczenia odpowiedniego pola w for-
        mularzu. Drugi sposób to rozró nianie mechanizmu oceny na podstawie struktury cią-
        gu określającego bazę oceny. Jeśli baza wyra ona jest prostą odpowiedzią, wybierany
        jest mechanizm prostego porównania-dopasowania (/CVEJ/CTMGT):
           RKúè

        Wybór mechanizmu MarkLogic sygnalizowany jest znakiem dwukropka poprzedzają-
        cego wyra enie oceny:
            KPRWV GSWCNU RKúè

        Z kolei ocena na podstawie dopasowania wyra enia regularnego wybierana jest w przy-
        padku rozpoznania w ciągu wzorca odpowiedzi znaków ukośników ograniczających
        wyra enie:
           RK

        Oto kod ilustrujący stosowanie poszczególnych klas:
            OCTMGTU  CTTC[
PGY 4GIGZR/CTMGT
 RK 
                            PGY /CVEJ/CTMGT
 RKúè 
                            PGY /CTM.QIKE/CTMGT
 KPRWV GSWCNU RKúè 

           HQTGCEJ 
 OCTMGTU CU OCTMGT ]
               RTKPV IGVAENCUU
 OCTMGT P 
                SWGUVKQP  PGY 6GZV3WGUVKQP
 +NG DQMÎY OC RKúEKQDQM!  OCTMGT
               HQTGCEJ
CTTC[
 RKúè  EVGT[  CU TGURQPUG ]
                   RTKPV VQFRQYKGF  TGURQPUG 
                   KH 
 SWGUVKQP OCTM
 TGURQPUG ]
                       RTKPV Y[ OKGPKVC QFRQYKGF P 
                   _ GNUG ]
                       RTKPV RQO[ MCP 
                   _
               _
           _

        Konstruujemy powy ej trzy obiekty strategii oceny, z których ka dy jest następnie wy-
        korzystywany do konstrukcji obiektu pytania 6GZV3WGUVKQP. Następnie ka dy z takich
        obiektów jest konfrontowany z dwoma przykładowymi odpowiedziami.
224                                                                    Część III ♦ Wzorce


      Klasa /CTM.QIKE/CTM jest w swej obecnej postaci jedynie makietą, a jej metoda OCTM

      ka dorazowo zwraca wartość VTWG. Oznaczony komentarzem kod da się jednak
      uruchomić w połączeniu z przykładową implementacją analizatora leksykalnego
      prezentowaną w dodatku B; mo na te ją przystosować do współpracy z analiza-
      torami autorstwa osób trzecich.

      Oto wynik wykonania powy szego kodu:
        4GIGZR/CTMGT
            QFRQYKGF  RKúè    Y[ OKGPKVC QFRQYKGF
            QFRQYKGF  EVGT[    RQO[ MC
        /CVEJ/CTMGT
            QFRQYKGF  RKúè    Y[ OKGPKVC QFRQYKGF
            QFRQYKGF  EVGT[    RQO[ MC
        /CTM.QIKE/CTMGT
            QFRQYKGF  RKúè    Y[ OKGPKVC QFRQYKGF
            QFRQYKGF  EVGT[    Y[ OKGPKVC QFRQYKGF

      Klasa /CTM.QIKE/CTMGT jest w tej chwili jedynie atrapą. Jej metoda oceny daje zawsze
      wartość VTWG, przez co w powy szym kodzie obie udzielone odpowiedzi są rozpozna-
      wane jako poprawne.

      W tym przykładzie obserwowaliśmy przekazywanie konkretnych danych od u ytkow-
      nika (podającego na wejście wartość zmiennej TGURQPUG) do obiektu strategii oceny;
      przekazanie odbywało się za pośrednictwem metody 3WGUVKQPOCTM
. W pewnych
      sytuacjach nie zawsze znana z góry jest ilość informacji wymaganych przez obiekt, na
      rzecz którego wywoływana jest operacja. Decyzję co do ilości i rodzaju pozyskiwanych
      danych mo na więc oddelegować, przekazując do obiektu strategii egzemplarz obiektu
      reprezentującego u ytkownika. Wtedy obiekt strategii mo e wywoływać na rzecz obiektu
      u ytkownika metody zwracające wymagane dane.



Wzorzec Observer
      Znamy ju pojęcie ortogonalności jako jednej z cnót projektu. Jednym z naszych (pro-
      gramistów) celów powinno być konstruowanie komponentów, które mo na swobodnie
      zmieniać albo przenosić, a których modyfikacje nie przenoszą się na pozostałe kom-
      ponenty. Jeśli ka da zmiana jednego z komponentów systemu prowokuje szereg zmian
      w innej części systemu, programowanie zmienia się w wyszukiwanie i poprawianie
      błędów wprowadzanych w coraz większej liczbie.

      Rzecz jasna nie zawsze da się osiągnąć po ądaną ortogonalność projektu. Elementy
      systemu muszą przecie dysponować referencjami do pozostałych części systemu.
      Mo na jednak minimalizować zawiązywane w ten sposób zale ności. Obserwowali-
      śmy ju choćby ró ne przykłady zastosowań polimorfizmu, dzięki któremu u ytkownik
      musi jedynie poznać i korzysta wyłącznie z interfejsu komponentu, zaś jego właściwa
      implementacja pozostaje poza zakresem jego zainteresowań.
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                         225


        W pewnych okolicznościach komponenty mo na oddalić od siebie jeszcze bardziej.
        Weźmy jako przykład klasę odpowiedzialną za pośredniczenie w dostępie u ytkownika
        do systemu:
           ENCUU .QIKP ]
               EQPUV .1)+0A75'4A70-0190  
               EQPUV .1)+0A9410)A2#55  
               EQPUV .1)+0A#%%'55  
               RTKXCVG UVCVWU  CTTC[


               HWPEVKQP JCPFNG.QIKP
 WUGT RCUU KR ]
                   UYKVEJ
TCPF
  ]
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A#%%'55 WUGT KR
                            TGV  VTWG DTGCM
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55 WUGT KR
                            TGV  HCNUG DTGCM
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A75'4A70-0190 WUGT KR
                            TGV  HCNUG DTGCM
                   _
                   TGVWTP TGV
               _

               RTKXCVG HWPEVKQP UGV5VCVWU
 UVCVWU WUGT KR ]
                    VJKU UVCVWU  CTTC[
 UVCVWU WUGT KR
               _

               HWPEVKQP IGV5VCVWU
 ]
                   TGVWTP VJKU UVCVWU
               _
           _

        Klasa ta imituje proces logowania się u ytkownika w systemie — wynik logowania
        określany jest losowo, na podstawie wartości wywołania funkcji TCPF
. Znacznik sta-
        tusu u ytkownika mo e w wyniku „logowania” przyjąć wartość .1)+0A#%%'55 (przyznany
        dostęp do systemu), .1)+0A9410)A2#55 (niepoprawne hasło) bądź .1)+0A75'4A70-0190
        (niepoprawne konto).

        Poniewa klasa .QIKP to stra nik systemowych skarbów, będzie cieszyć się w czasie
        implementacji projektu (i zapewne równie później) szczególną uwagą. Mo e się oka-
        zać, e w przyszłości kierownictwo działu marketingu za ąda utrzymywania w reje-
        strze logowania nazw domenowych u ytkowników. Łatwo będzie wprowadzić ądane
        uzupełnienie:
           HWPEVKQP JCPFNG.QIKP
 WUGT RCUU KR ]
               UYKVEJ
TCPF
  ]
                   ECUG 
                        VJKU UGV5VCVWU
UGNH.1)+0A#%%'55 WUGT KR
                        TGV  VTWG DTGCM
                   ECUG 
                        VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55 WUGT KR
                        TGV  HCNUG DTGCM
                   ECUG
226                                                                     Część III ♦ Wzorce


                     VJKU UGV5VCVWU
UGNH.1)+0A75'4A70-0190 WUGT KR
                     TGV  HCNUG DTGCM
            _
            .QIIGTNQI+2
 WUGT KR VJKU IGV5VCVWU

            TGVWTP TGV
        _

      Nieustający w trosce o bezpieczeństwo administratorzy mogą z kolei za ądać powia-
      damiania o nieudanych próbach logowania. Trzeba będzie ponownie wrócić do imple-
      mentacji metody JCPFNG.QIKP
 i umieścić w jej ciele dodatkowe wywołanie:
        KH 
 TGV ]
            0QVKHKGTOCKN9CTPKPI
 WUGT KR VJKU IGV5VCVWU

        _

      Nie mo na wykluczyć, e w nieokreślonej przyszłości sekcja rozwoju ogłosi strategicz-
      ne połączenie działalności z pewnym dostawcą usług internetowych i za ąda ustawiania
      dla pewnej grupy u ytkowników wyró niających ich ciasteczek. I tak dalej, i tak dalej.

      Wszystkie te ądania z osobna są proste do spełnienia, ale zawsze ich realizacja odby-
      wa się kosztem projektu. Klasa .QIKP niechybnie stanie się w ich wyniku klasą głębo-
      ko osadzoną w konkretnym systemie. Nie da się jej potem łatwo wyciągnąć z projektu
      i zastosować w kolejnym — trzeba będzie „obrać” jej kod z wszystkich naleciałości
      charakterystycznych dla systemu, w którym była osadzona. Jeśli nawet oka e się to
      nieskomplikowane, powrócimy do programowania opartego nie na projekcie, a na
      umiejętnym na wycinaniu i wklejaniu kodu. W efekcie otrzymamy zaś w dwóch ró -
      nych systemach dwie niepodobne ju do siebie klasy .QIKP, a ulepszenia jednej z nich
      będziemy próbować niezale nie wprowadzić w drugiej, a synchronizacja taka stanie
      się niemo liwa z powodu zbyt wielkiej ich odmienności.

      Có mo emy zrobić, aby zachować klasę .QIKP? Mo emy wdro yć wzorzec Observer.


Implementacja
      Sedno wzorca Observer (obserwator) polega na rozdzieleniu elementów u ytkujących
      (obserwatorów) od klasy centralnej (podmiotu obserwacji). Obserwatory muszą być
      informowane o zdarzeniach zachodzących w podmiocie obserwacji. Równocześnie nie
      chcemy wprowadzać trwałych i sztywnych zale ności pomiędzy podmiotem obserwa-
      cji a klasami obserwatorów.

      Mo emy więc umo liwić obserwatorom rejestrowanie się w klasie podmiotu. W tym
      celu powinniśmy uzupełnić klasę .QIKP o trzy nowe metody: rejestracji (CVVCEJ
), re-
      zygnacji (FGVCEJ
) i powiadomienia (PQVKH[
), przystosowując klasę do wymogów
      wyró niających podmioty obserwacji interfejsu (tutaj ma on nazwę 1DUGTXCDNG):
        KPVGTHCEG 1DUGTXCDNG ]
            HWPEVKQP CVVCEJ
1DUGTXGT QDUGTXGT
            HWPEVKQP FGVCEJ
1DUGTXGT QDUGTXGT
            HWPEVKQP PQVKH[

        _
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                         227

            Klasa Login…
               RTKXCVG QDUGTXGTU
                …
               HWPEVKQP CVVCEJ
1DUGTXGT QDUGTXGT ]
                     VJKU QDUGTXGTU=?  QDUGTXGT
               _

               HWPEVKQP FGVCEJ
1DUGTXGT QDUGTXGT ]
                    VJKU QDUGTXGTU  CTTC[AFKHH
 VJKU QDUGTXGTU CTTC[
 QDUGTXGT
               _

               HWPEVKQP PQVKH[
 ]
                   HQTGCEJ
 VJKU QDUGTXGTU CU QDU ]
                        QDU WRFCVG
 VJKU
                   _
               _
            …

        Mamy więc klasę podmiotu utrzymującą listę obiektów-obserwatorów. Obiekty te są
        dodawane do listy z zewnątrz poprzez wywołanie metody CVVCEJ
. Rezygnacja z ob-
        serwacji i usunięcie z listy następuje w wyniku wywołania metody FGVCEJ
. Z kolei
        wywołanie metody PQVKH[
 słu y jako powiadomienie obiektów obserwatorów o po-
        tencjalnie interesujących ich zdarzeniach. Implementacja tej metody sprowadza się do
        przejrzenia tablicy obiektów obserwatorów i wywołania na rzecz ka dego z nich me-
        tody WRFCVG
.

        Wywołanie metody rozsyłającej powiadomienia następuje we wnętrzu klasy .QIKP,
        w ciele metody JCPFNG.QIKP
:
           HWPEVKQP JCPFNG.QIKP
 WUGT RCUU KR ]
               UYKVEJ
TCPF
  ]
                   ECUG 
                        VJKU UGV5VCVWU
UGNH.1)+0A#%%'55 WUGT KR
                        TGV  VTWG DTGCM
                   ECUG 
                        VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55 WUGT KR
                        TGV  HCNUG DTGCM
                   ECUG 
                        VJKU UGV5VCVWU
UGNH.1)+0A75'4A70-0190 WUGT KR
                        TGV  HCNUG DTGCM
               _
                VJKU PQVKH[

               TGVWTP TGV
           _

        Zdefiniujmy interfejs klas-obserwatorów:
           KPVGTHCEG 1DUGTXGT ]
               HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG
           _

        Do listy obserwatorów mo na dodawać (za pośrednictwem metody CVVCEJ
 klasy pod-
        miotu obserwacji) dowolne obiekty, które implementują interfejs 1DUGTXCDNG. Utwórzmy
        kilka takich obiektów:
           ENCUU 5GEWTKV[/QPKVQT GZVGPFU 1DUGTXGT ]
               HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                    UVCVWU  QDUGTXCDNG IGV5VCVWU
228                                                                        Część III ♦ Wzorce


                  KH 
 UVCVWU=?  .QIKP.1)+0A9410)A2#55 ]
                       wyślij wiadomość do administratora…
                      RTKPV AA%.#55AA VY[U[ CO YKCFQOQ EK GOCKN FQ CFOKPKUVTCVQTCP 
                  _
              _
        _

        ENCUU )GPGTCN.QIIGT GZVGPFU 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                 UVCVWU  QDUGTXCDNG IGV5VCVWU

                 dodaj dane sesji logowania do rejestru…
                RTKPV AA%.#55AA VFQFCLú YRKU FQ TGLGUVTW NQIQYCPKCP 
            _
        _

        ENCUU 2CTVPGTUJKR6QQN GZVGPFU 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                 UVCVWU  QDUGTXCDNG IGV5VCVWU

                 sprawdź adres IP…
                 jeśli adres rozpoznany, ustaw plik cookie…
                RTKPV AA%.#55AA VWUVCYKCO RNKM EQQMKG FNC TQRQPCPGIQ CFTGUW +2P 
            _
        _

      Zauwa my, e obiekty-obserwatory mogą korzystać z przekazanego egzemplarza
      1DUGTXCDNG celem pozyskania dodatkowych informacji o zdarzeniu. Klasa podmiotu ob-
      serwacji powinna więc przewidywać stosowne metody udostępniające dane interesu-
      jące obserwatorów. U nas rolę tego interfejsu pełni metoda IGV5VCVWU
, za pośred-
      nictwem której powiadamiane obiekty-obserwatory otrzymują migawkę bie ącego stanu
      logowania.

      W obiekcie klasy .QIKP mo na rejestrować dowolne obiekty, byle tylko implementowały
      interfejs 1DUGTXGT:
            NQIKP  PGY .QIKP

            NQIKP CVVCEJ
PGY 5GEWTKV[/QPKVQT

            NQIKP CVVCEJ
PGY )GPGTCN.QIIGT

            NQIKP CVVCEJ
PGY 2CTVPGTUJKR6QQN


      Otrzymaliśmy więc elastyczne powiązanie pomiędzy klasą-podmiotem obserwacji
      a klasami-obserwatorami. Diagram klas odpowiedni dla omawianego przykładu pre-
      zentowany jest na rysunku 11.6.

      Poznaliśmy ju najwa niejsze elementy kodu implementującego wzorzec Observer.
      Dla większej przejrzystości mo emy zebrać je na wspólnym listingu:
        KPVGTHCEG 1DUGTXCDNG ]
            HWPEVKQP CVVCEJ
1DUGTXGT QDUGTXGT
            HWPEVKQP FGVCEJ
1DUGTXGT QDUGTXGT
            HWPEVKQP PQVKH[

        _

        ENCUU .QIKP KORNGOGPVU 1DUGTXCDNG ]
            RTKXCVG QDUGTXGTU  CTTC[

            EQPUV .1)+0A75'4A70-0190
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                         229




Rysunek 11.6. Klasy wzorca Observer

               EQPUV .1)+0A9410)A2#55  
               EQPUV .1)+0A#%%'55  
               RTKXCVG UVCVWU  CTTC[


               HWPEVKQP CVVCEJ
1DUGTXGT QDUGTXGT ]
                    VJKU QDUGTXGTU=?  QDUGTXGT
               _

               HWPEVKQP FGVCEJ
1DUGTXGT QDUGTXGT ]
                    VJKU QDUGTXGTU  CTTC[AFKHH
 VJKU QDUGTXGTU CTTC[
 QDUGTXGT
               _

               HWPEVKQP PQVKH[
 ]
                   HQTGCEJ
 VJKU QDUGTXGTU CU QDU ]
                        QDU WRFCVG
 VJKU
                   _
               _

               HWPEVKQP JCPFNG.QIKP
 WUGT RCUU KR ]
                   UYKVEJ
TCPF
  ]
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A#%%'55 WUGT KR
                            TGV  VTWG DTGCM
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55 WUGT KR
                            TGV  HCNUG DTGCM
                       ECUG 
                            VJKU UGV5VCVWU
UGNH.1)+0A75'4A70-0190 WUGT KR
                            TGV  HCNUG DTGCM
                   _
                    VJKU PQVKH[

                   TGVWTP TGV
               _
230                                                                       Część III ♦ Wzorce


            RTKXCVG HWPEVKQP UGV5VCVWU
 UVCVWU WUGT KR ]
                 VJKU UVCVWU  CTTC[
 UVCVWU WUGT KR
            _

            HWPEVKQP IGV5VCVWU
 ]
                TGVWTP VJKU UVCVWU
            _
        _

        KPVGTHCEG 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG
        _

        ENCUU 5GEWTKV[/QPKVQT GZVGPFU 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                 UVCVWU  QDUGTXCDNG IGV5VCVWU

                KH 
 UVCVWU=?  .QIKP.1)+0A9410)A2#55 ]
                     wyślij wiadomość do administratora…
                    RTKPV AA%.#55AA VY[U[ CO YKCFQOQ EK GOCKN FQ CFOKPKUVTCVQTCP 
                _
            _
        _

        ENCUU )GPGTCN.QIIGT GZVGPFU 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                 UVCVWU  QDUGTXCDNG IGV5VCVWU

                 dodaj dane sesji logowania do rejestru…
                RTKPV AA%.#55AA FQFCLú YRKU FQ TGLGUVTW NQIQYCPKCP 
            _
        _

        ENCUU 2CTVPGTUJKR6QQN GZVGPFU 1DUGTXGT ]
            HWPEVKQP WRFCVG
1DUGTXCDNG QDUGTXCDNG ]
                 UVCVWU  QDUGTXCDNG IGV5VCVWU

                 sprawdź adres IP…
                 jeśli adres rozpoznany, ustaw specjalne cookie…
                RTKPV AA%.#55AA WUVCYKCO RNKM EQQMKG FNC TQRQPCPGIQ CFTGUW +2P 
            _
        _

      Wzorzec ten doczekał się szeregu wariacji, nie jest te wolny od wad. Po pierwsze, meto-
      da zwracająca stan podmiotu obserwacji (IGV5VCVWU
) nie jest opisywana w interfejsie
      1DUGTXCDNG. Daje to typowi 1DUGTXCDNG nadzwyczajną elastyczność, ale równocześnie
      redukuje bezpieczeństwo typowania. Co się stanie, jeśli któryś z obiektów obserwato-
      rów odwołujących się do metody IGV5VCVWU
 zostanie zarejestrowany w obiekcie klasy
      implementującej interfejs 1DUGTXCDNG, ale nie implementującej metody IGV5VCVWU
?
      Có , wiadomo — dojdzie do błędu krytycznego.

      Jak zwykle mamy tu problem zrównowa enia elastyczności i ryzyka. Pominięcie w spe-
      cyfikacji interfejsu 1DUGTXCDNG daje mu elastyczność, ale nara a u ytkowników na ryzyko
      chybionego wywołania, jeśli obiekt obserwatora zarejestrowany zostanie w złym obiek-
      cie 1DUGTXCDNG. Ryzyko to mo na wyeliminować przez uzupełnienie interfejsu 1DUG
      TXCDNG o metodę IGV5VCVWU
, ale kosztem elastyczności. Niektóre z klas podmiotów
      obserwacji mogą bowiem na przykład udostępniać więcej ni jedną metodę zwracają-
      cą status.
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                           231


        Mo na by rozwiązać problem, przekazując w wywołaniu metody WRFCVG
 obiektów-
        obserwatorów nie egzemplarz podmiotu obserwacji, ale komplet informacji o jego
        stanie. Osobiście często stosuję tę metodę, jeśli mam na szybko skonstruować działa-
        jące rozwiązanie. W naszym przykładzie metoda WRFCVG
 powinna więc oczekiwać
        przekazania nie egzemplarza klasy .QIKP, ale znacznika statusu logowania, identyfikato-
        ra u ytkownika i adresu IP maszyny, z której zainicjowano próbę logowania, najlepiej
        w postaci tablicy. Pozwala to na wyeliminowanie jednej metody z klasy .QIKP. Z dru-
        giej strony, jeśli stan podmiotu obserwacji miałby być opisywany zbyt wielką liczbą
        danych, znacznie bardziej elastycznym rozwiązaniem byłoby jednak przekazywanie
        w wywołaniu WRFCVG
 egzemplarza .QIKP.

        Mo na te zablokować typ w ogóle, odmawiając w klasie .QIKP współpracy z obiektami
        klas innych ni wyró niona (np. .QIKP1DUGTXGT). W takim układzie nale ałoby jeszcze
        pomyśleć o jakichś realizowanych w czasie wykonania testach obiektów przekazywa-
        nych w wywołaniu metody CVVCEJ
; alternatywą byłaby zmiana (uszczegółowienie)
        interfejsu 1DUGTXCDNG.

        Mamy tu ponowne zastosowanie kompozycji w czasie wykonania celem skonstruowania
        elastycznego i rozszerzalnego modelu. Klasa .QIKP mo e zostać teraz łatwo wyodrębnio-
        na z kontekstu i przerzucona do zupełnie innego projektu, gdzie mo e współpracować
        z zupełnie odmiennym zestawem obserwatorów.



Wzorzec Visitor
        Jak widzieliśmy, wiele wzorców, podą ając za zasadą wy szości kompozycji nad dzie-
        dziczeniem, zakłada konstruowanie struktur w czasie wykonania programu. Znakomi-
        tym przykładem takiego wzorca jest powszechnie stosowany wzorzec kompozycji —
        Composite. Tam, gdzie trzeba operować na zbiorach obiektów, niektóre z operacji mogą
        odwoływać się do zbiorów jako takich, ale inne mogą wymagać operowania na poszcze-
        gólnych komponentach zbioru. Takie operacje mo na wbudować w same komponenty
        — w końcu to one znajdują się na najlepszej mo liwej pozycji do ich realizacji.

        Podejście to nie jest jednak pozbawione wad. Nie zawsze na przykład mamy dostateczną
        ilość informacji o operacjach, które będą wykonywane na strukturze. Jeśli klasy są uzu-
        pełniane operacjami od przypadku do przypadku, ich interfejsy mogą się nadmiernie
        rozrosnąć. Wtedy mo na uciec się do wzorca Visitor (wizytator).


Problem
        Wróćmy do prezentowanego w poprzednim rozdziale przykładu zastosowania wzorca
        kompozycji. Na potrzeby pewnej gry stworzyliśmy tam armię komponentów o ciekawej
        cesze zastępowalności komponentu zbiorem komponentów. Operacje były tam wbu-
        dowywane w same komponenty — właściwe operacje realizowane były przez obiekty
        składowe, do których odwoływał się obiekt-kompozyt.
232                                                                    Część III ♦ Wzorce

        ENCUU #TO[ GZVGPFU %QORQUKVG7PKV ]

            HWPEVKQP DQODCTF5VTGPIVJ
 ]
                 TGV  
                HQTGCEJ
 VJKU WPKVU
 CU WPKV ]
                     TGV 
 WPKV DQODCTF5VTGPIVJ

                _
                TGVWTP TGV
            _
        _

        ENCUU .CUGT%CPPQP7PKV GZVGPFU 7PKV ]
            HWPEVKQP DQODCTF5VTGPIVJ
 ]
                TGVWTP 
            _
        _

      Nie są tu problemem te operacje, które stanowią podstawowe zadania klasy kompozytu.
      Gorzej z operacjami pobocznymi.

      Weźmy choćby operację, w ramach której trzeba wykonać zrzut (w postaci tekstowej)
      informacji o obiektach składowych kompozytu. Operację taką mo na by włączyć do
      klasy 7PKV:
         klasa Unit
        HWPEVKQP VGZVWOR
 PWO   ]
              TGV  
              RCF
PWO
              TGV  URTKPVH
 ] RCF_U  
              TGV  IGVAENCUU
 VJKU  
              TGV  UK C TC GPKC  VJKU DQODCTF5VTGPIVJ
 P 
            TGVWTP TGV
        _

      Metodę tę mo na następnie przesłonić w klasie %QORQUKVG7PKV:
         klasa CompositeUnit
        HWPEVKQP VGZVWOR
 PWO   ]
              TGV  
              RCF
PWO
              TGV  URTKPVH
 ] RCF_U  
              TGV  IGVAENCUU
 VJKU  
              TGV  UK C TC GPKC  VJKU DQODCTF5VTGPIVJ
 P 
            HQTGCEJ
 VJKU WPKVU CU WPKV ]
                  TGV  WPKV VGZVWOR
 PWO 
 
            _
            TGVWTP TGV
        _

      Moglibyśmy, idąc tym tropem, utworzyć metody zliczające liczbę jednostek w kompo-
      zycie, zapisywania danych o składowych kompozytu w bazie danych czy te obliczania
      liczby jednostek aprowizacji konsumowanych codziennie przez armię.

      Ale czy koniecznie powinniśmy włączać tego rodzaju operacje do interfejsu kompozytu?
      Po co rozdymać interfejs o funkcje niekoniecznie związane z podstawowym zadaniem
      klasy? Odpowiedź jest prosta: postanowiliśmy zdefiniować te funkcje tu, bo z tego
      miejsca łatwo o dostęp do składowych kompozytu.
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                         233


        Choć co prawda łatwość przeglądania zbioru jest jedną z podstawowych cech kompo-
        zytu, nie oznacza to, e dosłownie ka da operacja wymagająca przejrzenia składowych
        kompozytu powinna być implementowana w jego klasie i zajmować miejsce w jego
        interfejsie.

        Mamy więc kolejny cel: wykorzystać w dowolnych operacjach łatwość odwołań do
        komponentów kompozytu bez niepotrzebnego rozdymania jego interfejsu.


Implementacja
        Zacznijmy od zdefiniowania w abstrakcyjnej klasie 7PKV metody CEEGRV
.
           HWPEVKQP CEEGRV
#TO[8KUKVQT XKUKVQT ]
                OGVJQF  XKUKV IGV%NCUU
 VJKU
                XKUKVQT OGVJQF
 VJKU
           _

        Jak widać, metoda CEEGRV
 oczekuje przekazania w wywołaniu obiektu klasy #TO[
        8KUKVQT. W języku PHP mamy mo liwość dynamicznego konstruowania nazw metod
        wykorzystywaną tu do realizacji dynamicznego wyboru metody do wywołania na rzecz
        przekazanego obiektu. Dzięki temu nie musimy implementować metody CEEGRV

        osobno dla ka dego węzła końcowego naszej hierarchii klas. Trzeba jedynie zdefi-
        niować tę samą metodę w abstrakcyjnej klasie kompozytu.
           HWPEVKQP CEEGRV
#TO[8KUKVQT XKUKVQT ]
                OGVJQF  XKUKV IGV%NCUU
 VJKU
                XKUKVQT OGVJQF
 VJKU
               HQTGCEJ
 VJKU WPKVU CU VJKUWPKV ]
                    VJKUWPKV CEEGRV
 XKUKVQT
               _
           _

        Metoda ta realizuje to samo zadanie co 7PKVCEEGRV
, z jednym tylko dodatkiem. Na
        podstawie nazwy bie ącej klasy konstruuje nazwę metody do wywołania i wywołuje
        ją na rzecz przekazanego obiektu klasy #TO[8KUKVQT. Jeśli więc bie ącą klasą będzie
        #TO[, nastąpi wywołanie klasy #TO[8KUKVQTXKUKV#TO[
; jeśli bie ącą klasą będzie
        6TQQR%CTTKGT, metoda zrealizuje wywołanie #TO[8KUKVQTXKUKV6TQQR%CTTKGT
 i tak
        dalej. Po powrocie z wywołania rozpocznie się zaś pętla przeglądająca komponenty
        kompozytu i wywołująca na ich rzecz ich implementację metody CEEGRV
. A poniewa
        CEEGRV
 powtarza tu operacje definiowane w klasach nadrzędnych, mo emy w prosty
        sposób wyeliminować duplikację kodu:
           HWPEVKQP CEEGRV
#TO[8KUKVQT XKUKVQT ]
               RCTGPVCEEGRV
 XKUKVQT
               HQTGCEJ
 VJKU WPKVU CU VJKUWPKV ]
                    VJKUWPKV CEEGRV
 XKUKVQT
               _
           _

        Takie ulepszenie jest bardzo eleganckie, ale choć tutaj dało oszczędność jednego za-
        ledwie wiersza, odbyło się z pewną szkodą dla czytelności i przejrzystości kodu. Tak
        czy inaczej, metoda CEEGRV
 pozwala nam na dwie rzeczy:
234                                                                      Część III ♦ Wzorce


            wywoływanie metody wizytacji właściwej dla bie ącego komponentu;
            przekazywanie obiektu wizytatora do wszystkich komponentów bie ącego
            kompozytu przez wywołanie ich metod CEEGRV
.

      Trzeba nam jeszcze zdefiniować interfejs klasy #TO[8KUKVQT. Pewne pojęcie o jego
      składnikach daje ju metoda CEEGRV
. Otó klasa wizytatora powinna definiować wer-
      sje metody CEEGRV
 dla wszystkich konkretnych klas w hierarchii. Dzięki temu na
      kompozytach ró nych obiektów będzie mo na wykonywać ró ne operacje. W mojej
      wersji tej klasy zdefiniowałem domyślne wersje metody XKUKV
 wywoływane auto-
      matycznie, jeśli klasa implementująca nie określi własnej wersji tej operacji dla danej
      klasy hierarchii 7PKV.
        CDUVTCEV ENCUU #TO[8KUKVQT ]
            CDUVTCEV HWPEVKQP XKUKV
7PKV PQFG

             HWPEVKQP XKUKV#TEJGT
#TEJGT PQFG ]
                  VJKU XKUKV
 PQFG
             _

             HWPEVKQP XKUKV%CXCNT[
%CXCNT[ PQFG ]
                  VJKU XKUKV
 PQFG
             _

             HWPEVKQP XKUKV.CUGT%CPPQP7PKV
.CUGT%CPPQP7PKV PQFG ]
                  VJKU XKUKV
 PQFG
             _

             HWPEVKQP XKUKV6TQQR%CTTKGT7PKV
6TQQR%CTTKGT7PKV PQFG ]
                  VJKU XKUKV
 PQFG
             _

             HWPEVKQP XKUKV#TO[
#TO[ PQFG ]
                  VJKU XKUKV
 PQFG
             _
        _

      Teraz więc problem sprowadza się do implementacji klas pochodnych #TO[8KUKVQT. Oto
      przykład w postaci kodu generującego zestawienie informacji o obiektach-kompozytach
      przeniesiony ju do klasy #TO[8KUKVQT:
        ENCUU 6GZVWOR#TO[8KUKVQT GZVGPFU #TO[8KUKVQT ]
            RTKXCVG VGZV  

             HWPEVKQP XKUKV
7PKV PQFG ]
                  TGV  
                  RCF
PQFG IGVGRVJ

                  TGV  URTKPVH
 ] RCF_U  
                  TGV  IGVAENCUU
 PQFG
                  TGV  UK C TC GPKC  PQFG DQODCTF5VTGPIVJ
 P 
                  VJKU VGZV  TGV
             _
             HWPEVKQP IGV6GZV
 ]
                 TGVWTP VJKU VGZV
             _
        _
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                          235


        Spójrzmy, jak stosować taki kod:
            OCKPACTO[  PGY #TO[

            OCKPACTO[ CFF7PKV
PGY #TEJGT

            OCKPACTO[ CFF7PKV
PGY .CUGT%CPPQP7PKV

            OCKPACTO[ CFF7PKV
PGY %CXCNT[


            VGZFWOR  PGY 6GZVWOR#TO[8KUKVQT

            OCKPACTO[ CEEGRV
 VGZVFWOR
           RTKPV VGZVFWOR IGV6GZV


        Powy szy kod powinien dać następujący rezultat:
           #TO[ UK C TC GPKC 
               #TEJGT UK C TC GPKC 
               .CUGT%CPPQP7PKV UK C TC GPKC 
               %CXCNT[ UK C TC GPKC 

        Utworzyliśmy obiekt klasy #TO[. Poniewa jest to kompozyt, włączyliśmy do niego (za
        pomocą metody CFF7PKV
) pewną liczbę utworzonych specjalnie w tym celu obiektów
        klasy 7PKV. Następnie utworzyliśmy obiekt klasy 6GZVWOR#TO[8KUKVQT i przekazaliśmy
        go w wywołaniu metody #TO[CEEGRV
. Metoda ta skonstruowała na podstawie nazwy
        klasy przekazanego obiektu nazwę metody do wywołania i wywołała metodę 6GZVWO
        R#TO[8KUKVQTXKUKV#TO[
. Poniewa nie przewidzieliśmy specjalnej obsługi wy-
        wołania XKUKV
 dla obiektów klasy #TO[, wywołanie to zostanie zrealizowane domyślną
        wersją metody XKUKV
 dla obiektów tego typu. W wywołaniu XKUKV
 przekazywana
        jest referencja obiektu klasy #TO[, a w samej metodzie następują wywołania metod
        tego obiektu (w tym nowej metody IGVGRVJ
, informującej o bie ącym zagłębieniu
        w drzewie kompozytu), generując za ich pośrednictwem zestawienie opisujące kom-
        pozyt. Aby zestawienie było kompletne, metoda #TO[CEEGRV
 wywołuje następnie
        metody CEEGRV
 komponentów, przekazując w wywołaniu ten sam obiekt wizytatora,
        który sama otrzymała. W ten sposób klasa #TO[8KUKVQT „odwiedza” wszystkie obiekty
        wchodzące w skład drzewa kompozytu.

        Uzupełniając istniejący szkielet klas o kilka zaledwie metod, utworzyliśmy mechanizm,
        za pośrednictwem którego mo na dołączać do klasy kompozytu nowe funkcje, nie in-
        gerując równocześnie w interfejs kompozytu i unikając powielania kodu przeglądania
        komponentów.

        Załó my teraz, e na niektórych polach planszy jednostki muszą uiszczać myto. Pobor-
        ca odwiedza wtedy poszczególne jednostki armii, przy czym ró ne jednostki są ró nie
        opodatkowane. Na tym przykładzie dobrze będzie widać zalety specjalizowania metod
        klasy wizytatora:
           ENCUU 6CZ%QNNGEVKQP8KUKVQT GZVGPFU #TO[8KUKVQT ]
               RTKXCVG FWG  
               RTKXCVG TGRQTV  

               HWPEVKQP XKUKV
7PKV PQFG ]
                    VJKU NGX[
 PQFG 
               _

               HWPEVKQP XKUKV#TEJGT
#TEJGT PQFG ]
                    VJKU NGX[
 PQFG 
               _
236                                                                     Część III ♦ Wzorce


            HWPEVKQP XKUKV%CXCNT[
%CXCNT[ PQFG ]
                 VJKU NGX[
 PQFG 
            _

            HWPEVKQP XKUKV6TQQR%CTTKGT7PKV
6TQQR%CTTKGT7PKV PQFG ]
                 VJKU NGX[
 PQFG 
            _

            RTKXCVG HWPEVKQP NGX[
7PKV WPKV COQWPV ]
                 VJKU TGRQTV  /[VQ PCNG PG C IGV%NCUU
 WPKV
                 VJKU TGRQTV   COQWPVP 
                 VJKU FWG 
 COQWPV
            _

            HWPEVKQP IGV4GRQTV
 ]
                TGVWTP VJKU TGRQTV
            _

            HWPEVKQP IGV6CZ
 ]
                TGVWTP VJKU FWG
            _
        _

      W tym prostym przykładzie nie skorzystamy wprost z obiektu klasy 7PKV przekazywa-
      nego do ró nych metod wizytacji. Korzystamy jedynie ze specjalizacji (podziału na
      klasy obiektów odwiedzanych), ustalając dla ró nych klas jednostek ró ne stawki myta.

      Oto jak wygląda pobieranie myta z punktu widzenia u ytkownika hierarchii:
         OCKPACTO[  PGY #TO[

         OCKPACTO[ CFF7PKV
PGY #TEJGT

         OCKPACTO[ CFF7PKV
PGY .CUGT%CPPQP7PKV

         OCKPACTO[ CFF7PKV
PGY %CXCNT[


         VCZEQNNGEVQT  PGY 6CZ%QNNGEVQT8KUKVQT

         OCKPACTO[ CEEGRV
 VCZEQNNGEVQT
        RTKPV ä%0+' 
        RTKPV VCZEQNNGEVQT IGV6CZ
 P 

      Tak jak poprzednio, do metody CEEGRV
 wywołanej na rzecz obiektu klasy #TO[ prze-
      kazany został obiekt wizytatora — tutaj 6CZ%QNNGEVQT8KUKVQT. Ponownie te obiekt
      klasy #TO[ przekazuje referencję do samego siebie do metody XKUKV#TO[
, tu przed
      oddelegowaniem wywołania do metod CEEGRV
 swoich komponentów. Komponenty
      są nieświadome operacji przeprowadzonych w ramach wizytacji. Ograniczają się do
      współpracy z publicznym interfejsem wizytatora, przekazując się po kolei do metody
      wizytacji właściwej dla swojego typu, w ramach której następuje obliczenie nale ne-
      go myta.

      Poza metodami zdefiniowanymi w klasie bazowej hierarchii wizytatorów klasa
      6CZ%QNNGEVQT8KUKVCVQT definiuje dwie metody dodatkowe: IGV4GRQTV
 i IGV6CZ
.
      Ich wywołania zwracają dane zebrane podczas wizytacji:
        /[VQ PCNG PG   C   #TO[ 
        /[VQ PCNG PG   C   #TEJGT 
        /[VQ PCNG PG   C   .CUGT%CPPQP7PKV 
        /[VQ PCNG PG   C   %CXCNT[ 
         ä%0+'
Rozdział 11. ♦ Reprezentacja i realizacja zadań                                           237


        Uczestników operacji prezentowanych w przykładzie ilustruje diagram z rysunku 11.7.




Rysunek 11.7. Wzorzec Visitor


Wady wzorca Visitor
        Wzorzec Visitor to kolejny wzorzec łączący prostotę z efektywnością. Zalety nie mogą
        jednak przesłonić całkowicie wad wzorca, gdy i te istnieją.

        Po pierwsze, choć najlepiej dopasowany do wzorca kompozycji, wizytator mo e być
        stosowany odnośnie dowolnych kolekcji obiektów. Da się więc na przykład zaimple-
        mentować wizytację list obiektów, w której ka dy z obiektów przechowuje referencję
        swoich sąsiadów.

        Wyodrębniając operacje na kolekcji poza nią samą, sprzeciwiamy się jednak hermety-
        zacji. Otó mo e się okazać, e aby wizytator mógł w jakikolwiek u yteczny sposób
        przetworzyć obiekty kolekcji, będą one musiały udostępniać na zewnątrz swoje aspekty
        wewnętrzne (prywatne). Widać to było ju choćby w pierwszym przykładzie z tego
        podrozdziału, kiedy to na potrzeby klasy wizytatora 6GZVWOR#TO[8KUKVQT trzeba było
        uzupełnić interfejs 7PKV o dodatkową metodę.

        Poniewa wzorzec ten zakłada równie oddzielenie iteracji od operacji wykonywanych
        na komponentach kolekcji, trzeba zrzec się pewnej części kontroli — nie da się na
        przykład łatwo utworzyć metody wizytacji XKUKV
, która wykonuje pewne operacje
        tak przed, jak i po odwiedzeniu komponentów zagnie d onych w kolekcji. Mo na by
        tę niedogodność wyeliminować, przenosząc odpowiedzialność za iterację do samych
        obiektów wizytatorów. Tyle e wtedy w obiektach tych dojdzie niechybnie do powie-
        lenia kodu iteracji.

        Osobiście preferuję więc obsługę iteracji w ramach klas wizytowanych, choć nie przeczę,
         e jej wysunięcie poza te klasy dałoby pewną zasadniczą zaletę: mo na wtedy zmieniać
        w poszczególnych wizytatorach sposób wizytacji.

More Related Content

What's hot

Programowanie skryptów powłoki
Programowanie skryptów powłokiProgramowanie skryptów powłoki
Programowanie skryptów powłoki
Wydawnictwo Helion
 
Programowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modeleProgramowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modele
Wydawnictwo Helion
 
PHP. Praktyczne wprowadzenie
PHP. Praktyczne wprowadzeniePHP. Praktyczne wprowadzenie
PHP. Praktyczne wprowadzenie
Wydawnictwo Helion
 
Head First Design Patterns. Edycja polska
Head First Design Patterns. Edycja polskaHead First Design Patterns. Edycja polska
Head First Design Patterns. Edycja polska
Wydawnictwo Helion
 
PHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie IIIPHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie III
Wydawnictwo Helion
 
Perl 6. Podstawy
Perl 6. PodstawyPerl 6. Podstawy
Perl 6. Podstawy
Wydawnictwo Helion
 
ABC Delphi 6
ABC Delphi 6ABC Delphi 6
ABC Delphi 6
Wydawnictwo Helion
 
Flash i PHP5. Podstawy
Flash i PHP5. PodstawyFlash i PHP5. Podstawy
Flash i PHP5. Podstawy
Wydawnictwo Helion
 
Język C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowaniaJęzyk C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowania
Wydawnictwo Helion
 
PHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie IIPHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie II
Wydawnictwo Helion
 
Programowanie. Od podstaw
Programowanie. Od podstawProgramowanie. Od podstaw
Programowanie. Od podstaw
Wydawnictwo Helion
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładu
Wydawnictwo Helion
 
Perl. Od podstaw
Perl. Od podstawPerl. Od podstaw
Perl. Od podstaw
Wydawnictwo Helion
 
PHP. Programowanie
PHP. ProgramowaniePHP. Programowanie
PHP. Programowanie
Wydawnictwo Helion
 

What's hot (14)

Programowanie skryptów powłoki
Programowanie skryptów powłokiProgramowanie skryptów powłoki
Programowanie skryptów powłoki
 
Programowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modeleProgramowanie. Koncepcje, techniki i modele
Programowanie. Koncepcje, techniki i modele
 
PHP. Praktyczne wprowadzenie
PHP. Praktyczne wprowadzeniePHP. Praktyczne wprowadzenie
PHP. Praktyczne wprowadzenie
 
Head First Design Patterns. Edycja polska
Head First Design Patterns. Edycja polskaHead First Design Patterns. Edycja polska
Head First Design Patterns. Edycja polska
 
PHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie IIIPHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie III
 
Perl 6. Podstawy
Perl 6. PodstawyPerl 6. Podstawy
Perl 6. Podstawy
 
ABC Delphi 6
ABC Delphi 6ABC Delphi 6
ABC Delphi 6
 
Flash i PHP5. Podstawy
Flash i PHP5. PodstawyFlash i PHP5. Podstawy
Flash i PHP5. Podstawy
 
Język C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowaniaJęzyk C++. Koncepcje i techniki programowania
Język C++. Koncepcje i techniki programowania
 
PHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie IIPHP. 101 praktycznych skryptów. Wydanie II
PHP. 101 praktycznych skryptów. Wydanie II
 
Programowanie. Od podstaw
Programowanie. Od podstawProgramowanie. Od podstaw
Programowanie. Od podstaw
 
C++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładuC++. Potęga języka. Od przykładu do przykładu
C++. Potęga języka. Od przykładu do przykładu
 
Perl. Od podstaw
Perl. Od podstawPerl. Od podstaw
Perl. Od podstaw
 
PHP. Programowanie
PHP. ProgramowaniePHP. Programowanie
PHP. Programowanie
 

Viewers also liked

Macromedia Flash MX 2004. Sztuka projektowania
Macromedia Flash MX 2004. Sztuka projektowaniaMacromedia Flash MX 2004. Sztuka projektowania
Macromedia Flash MX 2004. Sztuka projektowania
Wydawnictwo Helion
 
Eclipse. Podręcznik programisty
Eclipse. Podręcznik programistyEclipse. Podręcznik programisty
Eclipse. Podręcznik programisty
Wydawnictwo Helion
 
Wprowadzenie do systemów baz danych
Wprowadzenie do systemów baz danychWprowadzenie do systemów baz danych
Wprowadzenie do systemów baz danych
Wydawnictwo Helion
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Wydawnictwo Helion
 
PHP 5. Nowe możliwości
PHP 5. Nowe możliwościPHP 5. Nowe możliwości
PHP 5. Nowe możliwości
Wydawnictwo Helion
 
Mandrake Linux. Ćwiczenia zaawansowane
Mandrake Linux. Ćwiczenia zaawansowaneMandrake Linux. Ćwiczenia zaawansowane
Mandrake Linux. Ćwiczenia zaawansowane
Wydawnictwo Helion
 

Viewers also liked (6)

Macromedia Flash MX 2004. Sztuka projektowania
Macromedia Flash MX 2004. Sztuka projektowaniaMacromedia Flash MX 2004. Sztuka projektowania
Macromedia Flash MX 2004. Sztuka projektowania
 
Eclipse. Podręcznik programisty
Eclipse. Podręcznik programistyEclipse. Podręcznik programisty
Eclipse. Podręcznik programisty
 
Wprowadzenie do systemów baz danych
Wprowadzenie do systemów baz danychWprowadzenie do systemów baz danych
Wprowadzenie do systemów baz danych
 
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktykJęzyk C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
Język C++. Standardy kodowania. 101 zasad, wytycznych i zalecanych praktyk
 
PHP 5. Nowe możliwości
PHP 5. Nowe możliwościPHP 5. Nowe możliwości
PHP 5. Nowe możliwości
 
Mandrake Linux. Ćwiczenia zaawansowane
Mandrake Linux. Ćwiczenia zaawansowaneMandrake Linux. Ćwiczenia zaawansowane
Mandrake Linux. Ćwiczenia zaawansowane
 

Similar to PHP5. Obiekty, wzorce, narzędzia

PHP w mgnieniu oka
PHP w mgnieniu okaPHP w mgnieniu oka
PHP w mgnieniu oka
Wydawnictwo Helion
 
PHP4. Zaawansowane programowanie
PHP4. Zaawansowane programowaniePHP4. Zaawansowane programowanie
PHP4. Zaawansowane programowanie
Wydawnictwo Helion
 
PHP5. Księga eksperta
PHP5. Księga ekspertaPHP5. Księga eksperta
PHP5. Księga eksperta
Wydawnictwo Helion
 
PHP i MySQL. Aplikacje bazodanowe
PHP i MySQL. Aplikacje bazodanowePHP i MySQL. Aplikacje bazodanowe
PHP i MySQL. Aplikacje bazodanowe
Wydawnictwo Helion
 
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalistyPHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
Wydawnictwo Helion
 
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danychPHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
Wydawnictwo Helion
 
ABC Delphi 2006
ABC Delphi 2006ABC Delphi 2006
ABC Delphi 2006
Wydawnictwo Helion
 
PHP. Programowanie w systemie Windows. Vademecum profesjonalisty
PHP. Programowanie w systemie Windows. Vademecum profesjonalistyPHP. Programowanie w systemie Windows. Vademecum profesjonalisty
PHP. Programowanie w systemie Windows. Vademecum profesjonalisty
Wydawnictwo Helion
 
Delphi 8 .NET. Kompendium programisty
Delphi 8 .NET. Kompendium programistyDelphi 8 .NET. Kompendium programisty
Delphi 8 .NET. Kompendium programisty
Wydawnictwo Helion
 
PHP i MySQL. Wprowadzenie. Wydanie II
PHP i MySQL. Wprowadzenie. Wydanie IIPHP i MySQL. Wprowadzenie. Wydanie II
PHP i MySQL. Wprowadzenie. Wydanie II
Wydawnictwo Helion
 
PHP, MySQL i Apache dla każdego. Wydanie II
PHP, MySQL i Apache dla każdego. Wydanie IIPHP, MySQL i Apache dla każdego. Wydanie II
PHP, MySQL i Apache dla każdego. Wydanie II
Wydawnictwo Helion
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Wydawnictwo Helion
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie
Wydawnictwo Helion
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki startPHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki start
Wydawnictwo Helion
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie IIPHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
Wydawnictwo Helion
 
PHP, MySQL i Apache dla każdego. Wydanie III
PHP, MySQL i Apache dla każdego. Wydanie IIIPHP, MySQL i Apache dla każdego. Wydanie III
PHP, MySQL i Apache dla każdego. Wydanie III
Wydawnictwo Helion
 
PHP5, Apache i MySQL. Od podstaw
PHP5, Apache i MySQL. Od podstawPHP5, Apache i MySQL. Od podstaw
PHP5, Apache i MySQL. Od podstaw
Wydawnictwo Helion
 
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie IIPHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
Wydawnictwo Helion
 
Delphi. Szybki start
Delphi. Szybki startDelphi. Szybki start
Delphi. Szybki start
Wydawnictwo Helion
 
Visual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programistyVisual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programisty
Wydawnictwo Helion
 

Similar to PHP5. Obiekty, wzorce, narzędzia (20)

PHP w mgnieniu oka
PHP w mgnieniu okaPHP w mgnieniu oka
PHP w mgnieniu oka
 
PHP4. Zaawansowane programowanie
PHP4. Zaawansowane programowaniePHP4. Zaawansowane programowanie
PHP4. Zaawansowane programowanie
 
PHP5. Księga eksperta
PHP5. Księga ekspertaPHP5. Księga eksperta
PHP5. Księga eksperta
 
PHP i MySQL. Aplikacje bazodanowe
PHP i MySQL. Aplikacje bazodanowePHP i MySQL. Aplikacje bazodanowe
PHP i MySQL. Aplikacje bazodanowe
 
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalistyPHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
PHP i MySQL. Tworzenie stron WWW. Wydanie drugie. Vademecum profesjonalisty
 
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danychPHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
PHP, Microsoft IIS i SQL Server. Projektowanie i programowanie baz danych
 
ABC Delphi 2006
ABC Delphi 2006ABC Delphi 2006
ABC Delphi 2006
 
PHP. Programowanie w systemie Windows. Vademecum profesjonalisty
PHP. Programowanie w systemie Windows. Vademecum profesjonalistyPHP. Programowanie w systemie Windows. Vademecum profesjonalisty
PHP. Programowanie w systemie Windows. Vademecum profesjonalisty
 
Delphi 8 .NET. Kompendium programisty
Delphi 8 .NET. Kompendium programistyDelphi 8 .NET. Kompendium programisty
Delphi 8 .NET. Kompendium programisty
 
PHP i MySQL. Wprowadzenie. Wydanie II
PHP i MySQL. Wprowadzenie. Wydanie IIPHP i MySQL. Wprowadzenie. Wydanie II
PHP i MySQL. Wprowadzenie. Wydanie II
 
PHP, MySQL i Apache dla każdego. Wydanie II
PHP, MySQL i Apache dla każdego. Wydanie IIPHP, MySQL i Apache dla każdego. Wydanie II
PHP, MySQL i Apache dla każdego. Wydanie II
 
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0Struktury danych i techniki obiektowe na przykładzie Javy 5.0
Struktury danych i techniki obiektowe na przykładzie Javy 5.0
 
.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie.NET Framework 2.0. Zaawansowane programowanie
.NET Framework 2.0. Zaawansowane programowanie
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki startPHP i MySQL. Dynamiczne strony WWW. Szybki start
PHP i MySQL. Dynamiczne strony WWW. Szybki start
 
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie IIPHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
PHP i MySQL. Dynamiczne strony WWW. Szybki start. Wydanie II
 
PHP, MySQL i Apache dla każdego. Wydanie III
PHP, MySQL i Apache dla każdego. Wydanie IIIPHP, MySQL i Apache dla każdego. Wydanie III
PHP, MySQL i Apache dla każdego. Wydanie III
 
PHP5, Apache i MySQL. Od podstaw
PHP5, Apache i MySQL. Od podstawPHP5, Apache i MySQL. Od podstaw
PHP5, Apache i MySQL. Od podstaw
 
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie IIPHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
PHP i MySQL. Tworzenie sklepów internetowych. Wydanie II
 
Delphi. Szybki start
Delphi. Szybki startDelphi. Szybki start
Delphi. Szybki start
 
Visual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programistyVisual C# 2005. Zapiski programisty
Visual C# 2005. Zapiski programisty
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
Wydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
Wydawnictwo Helion
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
Wydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Wydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
Wydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Wydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Wydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
Wydawnictwo Helion
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
Wydawnictwo Helion
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
Wydawnictwo Helion
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
Wydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
Wydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
Wydawnictwo Helion
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
Wydawnictwo Helion
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
Wydawnictwo Helion
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
Wydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
Wydawnictwo Helion
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
Wydawnictwo Helion
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
Wydawnictwo Helion
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
Wydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Java. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie IIJava. Efektywne programowanie. Wydanie II
Java. Efektywne programowanie. Wydanie II
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 

PHP5. Obiekty, wzorce, narzędzia

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI PHP5. Obiekty, wzorce, narzêdzia KATALOG KSI¥¯EK Autor: Matt Zandstra KATALOG ONLINE T³umaczenie: Przemys³aw Szeremiota ISBN: 83-7361-868-6 ZAMÓW DRUKOWANY KATALOG Tytu³ orygina³u: PHP 5 Objects, Patterns, and Practice Format: B5, stron: 464 TWÓJ KOSZYK Profesjonalne techniki programowania obiektowego w PHP5 DODAJ DO KOSZYKA • Poznaj zasady projektowania i programowania obiektowego • Zastosuj wzorce projektowe podczas tworzenia aplikacji • Wykorzystaj narzêdzia wspomagaj¹ce pracê programisty PHP5 CENNIK I INFORMACJE Wraz z rosn¹c¹ popularno ci¹ jêzyka PHP zwiêksza siê równie¿ zakres jego zastosowañ. Za pomoc¹ PHP tworzy siê ju¿ nie tylko proste dynamiczne witryny WWW ZAMÓW INFORMACJE i fora dyskusyjne, ale równie¿ rozbudowane aplikacje sieciowe, wykorzystywane czêsto O NOWO CIACH w du¿ych przedsiêbiorstwach. Ju¿ w PHP4 zaimplementowano pewne mechanizmy u³atwiaj¹ce tworzenie rozbudowanych systemów, jednak dopiero PHP5 sta³ siê w pe³ni ZAMÓW CENNIK obiektowym jêzykiem programowania pozwalaj¹cym na korzystanie z wszystkich wynikaj¹cych z tego mo¿liwo ci. „PHP5. Obiekty, wzorce i narzêdzia” stanowi dok³adne omówienie wszystkich technik CZYTELNIA obiektowych w kontek cie zastosowania ich podczas tworzenia aplikacji w PHP5. Zawiera przegl¹d podstawowych i zaawansowanych cech PHP5 zwi¹zanych FRAGMENTY KSI¥¯EK ONLINE z obiektowo ci¹. Przedstawia przyk³ady najczê ciej wykorzystywanych wzorców projektowych i zasady ich stosowania. Ksi¹¿ka opisuje równie¿ narzêdzia, które mog¹ okazaæ siê bardzo przydatne podczas tworzenia rozbudowanych aplikacji, s³u¿¹ce do tworzenia dokumentacji i kontroli wersji plików. • Podstawowe pojêcia z dziedziny obiektowo ci • Obs³uga obiektów • Wyj¹tki i obs³uga b³êdów • Projektowanie obiektowe • Modelowanie obiektów w jêzyku UML • Wzorce projektowe • Stosowanie pakietu PEAR Wydawnictwo Helion • Generowanie dokumentacji za pomoc¹ PHPDocumentor ul. Chopina 6 • Zarz¹dzanie wersjami plików w systemie CVS 44-100 Gliwice • Tworzenie pakietów instalacyjnych tel. (32)230-98-63 Przekonaj siê, jak potê¿nym narzêdziem jest najnowsza wersja jêzyka PHP e-mail: helion@helion.pl
  • 2. Spis treści O Autorze ......................................................................................... 9 O Recenzencie Technicznym ........................................................... 10 Przedmowa ..................................................................................... 11 Część I Wprowadzenie ...............................................................13 Rozdział 1. PHP — projektowanie i zarządzanie ................................................. 15 Problem .......................................................................................................................... 15 PHP a inne języki programowania ................................................................................. 17 O ksią ce ........................................................................................................................ 19 Podsumowanie ............................................................................................................... 21 Część II Obiekty .........................................................................23 Rozdział 2. PHP a obiekty ................................................................................ 25 Nieoczekiwany sukces obiektów w PHP ........................................................................ 25 Debata obiektowa — za czy przeciw? ............................................................................ 28 Podsumowanie ............................................................................................................... 29 Rozdział 3. Obiektowy elementarz ..................................................................... 31 Klasy i obiekty ............................................................................................................... 31 Definiowanie składowych klasy ..................................................................................... 33 Metody ........................................................................................................................... 36 Typy argumentów metod ................................................................................................ 39 Dziedziczenie ................................................................................................................. 44 Podsumowanie ............................................................................................................... 58 Rozdział 4. Zaawansowana obsługa obiektów ................................................... 59 Metody i składowe statyczne .......................................................................................... 59 Składowe stałe ................................................................................................................ 63 Klasy abstrakcyjne ......................................................................................................... 63 Interfejsy ........................................................................................................................ 66 Obsługa błędów .............................................................................................................. 68 Klasy i metody finalne ................................................................................................... 75 Przechwytywanie chybionych wywołań ......................................................................... 76 Definiowanie destruktorów ............................................................................................ 80
  • 3. 6 PHP5. Obiekty, wzorce, narzędzia Wykonywanie kopii obiektów ........................................................................................ 81 Reprezentacja obiektu w ciągach znaków ...................................................................... 84 Podsumowanie ............................................................................................................... 85 Rozdział 5. Narzędzia obiektowe ....................................................................... 87 PHP a pakiety ................................................................................................................. 87 Klasy i funkcje pomocnicze ........................................................................................... 92 Reflection API ................................................................................................................ 99 Podsumowanie ............................................................................................................. 110 Rozdział 6. Obiekty a projektowanie ............................................................... 111 Jak rozumieć projektowanie? ....................................................................................... 111 Programowanie obiektowe i proceduralne ................................................................... 112 Zasięg klas .................................................................................................................... 117 Polimorfizm .................................................................................................................. 119 Hermetyzacja ................................................................................................................ 120 Niewa ne jak ................................................................................................................ 122 Cztery drogowskazy ..................................................................................................... 123 Język UML ................................................................................................................... 124 Podsumowanie ............................................................................................................. 133 Część III Wzorce .......................................................................135 Rozdział 7. Czym są wzorce projektowe? Do czego się przydają? ..................... 137 Czym są wzorce projektowe? ....................................................................................... 137 Wzorzec projektowy ..................................................................................................... 139 Format wzorca według Bandy Czworga ....................................................................... 141 Po co nam wzorce projektowe? .................................................................................... 142 Wzorce projektowe a PHP ............................................................................................ 144 Podsumowanie ............................................................................................................. 145 Rozdział 8. Wybrane prawidła wzorców ........................................................... 147 Olśnienie wzorcami ...................................................................................................... 147 Kompozycja i dziedziczenie ......................................................................................... 148 Rozprzęganie ................................................................................................................ 153 Kod ma u ywać interfejsów, nie implementacji ........................................................... 156 Zmienne koncepcje ....................................................................................................... 157 Nadmiar wzorców ........................................................................................................ 158 Wzorce ......................................................................................................................... 159 Podsumowanie ............................................................................................................. 160 Rozdział 9. Generowanie obiektów .................................................................. 161 Generowanie obiektów — problemy i rozwiązania ...................................................... 161 Wzorzec Singleton ....................................................................................................... 165 Wzorzec Factory Method ............................................................................................. 169 Wzorzec Abstract Factory ............................................................................................ 174 Prototyp ........................................................................................................................ 179 Ale to oszustwo! ......................................................................................................... 183 Podsumowanie ............................................................................................................. 185 Rozdział 10. Relacje między obiektami ............................................................. 187 Strukturalizacja klas pod kątem elastyczności obiektów .............................................. 187 Wzorzec Composite ..................................................................................................... 188 Wzorzec Decorator ....................................................................................................... 198 Wzorzec Facade ........................................................................................................... 205 Podsumowanie ............................................................................................................. 208
  • 4. Spis treści 7 Rozdział 11. Reprezentacja i realizacja zadań ................................................... 209 Wzorzec Interpreter ...................................................................................................... 209 Wzorzec Strategy ......................................................................................................... 219 Wzorzec Observer ........................................................................................................ 224 Wzorzec Visitor ............................................................................................................ 231 Wzorzec Command ...................................................................................................... 238 Podsumowanie ............................................................................................................. 242 Rozdział 12. Wzorce korporacyjne .................................................................... 245 Wprowadzenie .............................................................................................................. 245 Małe oszustwo na samym początku ............................................................................. 248 Warstwa prezentacji ..................................................................................................... 257 Warstwa logiki biznesowej ........................................................................................... 287 Warstwa danych ........................................................................................................... 295 Podsumowanie ............................................................................................................. 317 Część IV Narzędzia ....................................................................319 Rozdział 13. Dobre (i złe) praktyki .................................................................... 321 Nie tylko kod ................................................................................................................ 321 Pukanie do otwartych drzwi ......................................................................................... 322 Jak to zgrać? ................................................................................................................. 324 Uskrzydlanie kodu ........................................................................................................ 325 Dokumentacja ............................................................................................................... 326 Testowanie ................................................................................................................... 328 Podsumowanie ............................................................................................................. 336 Rozdział 14. PEAR ........................................................................................... 337 Czym jest PEAR? ......................................................................................................... 338 Instalowanie pakietu z repozytorium PEAR ................................................................. 338 Korzystanie z pakietu PEAR ........................................................................................ 340 Instalator pakietu PEAR ............................................................................................... 343 Podsumowanie ............................................................................................................. 352 Rozdział 15. Generowanie dokumentacji — phpDocumentor .............................. 353 Po co nam dokumentacja? ............................................................................................ 354 Instalacja ...................................................................................................................... 355 Generowanie dokumentacji .......................................................................................... 355 Komentarze DocBlock ................................................................................................. 357 Dokumentowanie klas .................................................................................................. 358 Dokumentowanie plików .............................................................................................. 360 Dokumentowanie składowych ...................................................................................... 360 Dokumentowanie metod ............................................................................................... 361 Tworzenie odnośników w dokumentacji ...................................................................... 363 Podsumowanie ............................................................................................................. 365 Rozdział 16. Zarządzanie wersjami projektu z CVS ............................................ 367 Po co nam CVS? .......................................................................................................... 367 Skąd wziąć CVS? ......................................................................................................... 368 Konfigurowanie repozytorium CVS ............................................................................. 369 Rozpoczynamy projekt ................................................................................................. 372 Aktualizacja i zatwierdzanie ......................................................................................... 374 Dodawanie i usuwanie plików i katalogów .................................................................. 377 Etykietowanie i eksportowanie wydania ........................................................................ 381 Rozgałęzianie projektu ................................................................................................. 383 Podsumowanie ............................................................................................................. 386
  • 5. 8 PHP5. Obiekty, wzorce, narzędzia Rozdział 17. Automatyzacja instalacji z Phing ................................................... 389 Czym jest Phing? .......................................................................................................... 390 Pobieranie i instalacja pakietu Phing ............................................................................ 391 Plik kompilacji — build.xml ........................................................................................ 391 Podsumowanie ............................................................................................................. 409 Część V Konkluzje ....................................................................411 Rozdział 18. Obiekty, wzorce, narzędzia ............................................................ 413 Obiekty ......................................................................................................................... 413 Wzorce ......................................................................................................................... 417 Narzędzia ...................................................................................................................... 420 Podsumowanie ............................................................................................................. 424 Dodatki ......................................................................................425 Dodatek A Bibliografia ................................................................................... 427 Ksią ki .......................................................................................................................... 427 Publikacje ..................................................................................................................... 428 Witryny WWW ............................................................................................................ 428 Dodatek B Prosty analizator leksykalny .......................................................... 429 Skaner ........................................................................................................................... 429 Analizator leksykalny ................................................................................................... 433 Skorowidz ..................................................................................... 445
  • 6. Rozdział 11. Reprezentacja i realizacja zadań W niniejszym rozdziale zaczniemy wreszcie działać i przyjrzymy się wzorcom projek- towym, które są pomocne w wykonywaniu zadań — od interpretacji minijęzyków po hermetyzacje algorytmów. Rozdział poświęcony będzie: Wzorcowi Interpreter — umo liwiającemu konstruowanie interpreterów minijęzyków nadające się do wbudowywania w aplikacje interfejsów skryptowych. Wzorcowi Strategy — zakładającemu identyfikowanie algorytmów stosowanych w systemie i ich hermetyzację do postaci osobnych, własnych typów. Wzorcowi Observer — tworzącemu zaczepy umo liwiające powiadamianie obiektów o zdarzeniach zachodzących w systemie. Wzorcowi Visitor — rozwiązującemu problem aplikacji operacji do wszystkich węzłów drzewa obiektów. Wzorcowi Command — obiektom poleceń przekazywanym pomiędzy częściami systemu. Wzorzec Interpreter Języki programowania powstają i są rozwijane (przynajmniej z początku) w innych językach programowania. PHP został na przykład „spisany” w języku C. Nic więc nie stoi na przeszkodzie, abyśmy, posługując się PHP, zdefiniowali i wykorzystywali wła- sny język programowania. Oczywiście ka dy utworzony tak język będzie powolny i dość ograniczony, ale nie oznacza to, e będzie bezu yteczny — minijęzyki są całkiem przy- datne, co postaram się zademonstrować w tym rozdziale.
  • 7. 210 Część III ♦ Wzorce Tworząc interfejsy WWW (ale równie interfejsy wiersza poleceń) w języku PHP, da- jemy u ytkownikowi dostęp do pewnego zestawu funkcji. Zawsze w takim przypadku stajemy przed wyborem pomiędzy prostotą korzystania z interfejsu a zakresem mo - liwości oddawanych w ręce u ytkownika. Im więcej mo liwości dla u ytkownika, tym z reguły bardziej zło ony i rozdrobniony interfejs. Bardzo pomocne jest tu staranne zaprojektowanie interfejsu i rozpoznanie potrzeb u ytkowników — jeśli 90 procent z nich wykorzystuje jedynie 30 procent (tych samych) funkcji systemu, koszt udostęp- niania maksimum funkcjonalności mo e okazać się za wysoki w stosunku do efektów. Mo na wtedy rozwa yć uproszczenie systemu pod kątem „przeciętnego” u ytkownika. Ale co wtedy z owymi 10 procentami u ytkowników zaawansowanych korzystających z kompletu zaawansowanych funkcji systemu? Ich potrzeby mo na by zaspokoić ina- czej, na przykład udostępniając im wewnętrzny język programowania, w którym będą mogli odwoływać się do wszystkich funkcji systemu. Mamy ju co prawda pod ręką jeden język programowania. Chodzi o PHP. Moglibyśmy więc udostępnić go u ytkownikom i pozwolić im na tworzenie własnych skryptów: HQTOAKPRWV RTKPV HKNGAIGVAEQPVGPVU GVERCUUYF GXCN HQTOAKPRWV Jednak e takie rozszerzenie dostępności systemu wydaje się szaleństwem. Jeśli Czytel- nik nie jest przekonany co do nonsensowności tego pomysłu, powinien przypomnieć sobie o dwóch kwestiach: bezpieczeństwie i zło oności. Kwestia bezpieczeństwa jest dobrze ilustrowana w naszym przykładzie — umo liwiając u ytkownikom uzupełnia- nie systemu o ich własny kod w języku PHP, dajemy im w rzeczy samej pełny dostęp do serwera, na którym działa nasza aplikacja. Równie du ym problemem jest jednak zło oność — niezale nie od przejrzystości kodu aplikacji przeciętny u ytkownik będzie miał problemy z jej rozszerzeniem, zwłaszcza, jeśli ma z nią kontakt jednie za pośred- nictwem okna przeglądarki. Problemy te mo na wyeliminować, opracowując i udostępniając u ytkownikom własny minijęzyk. Mo na w nim połączyć elastyczność, zredukować mo liwość wyrządzania szkód przez u ytkowników i równocześnie zadbać o zwartość całości. Wyobraźmy sobie aplikację do tworzenia quizów. Autorzy mieliby układać pytania i ustalać reguły oznaczania poprawności odpowiedzi udzielanych przez uczestników quizu. Chodziłoby o to, eby quizy toczyły się bez interwencji operatora, choć część odpowiedzi miała by być wprowadzana przez uczestników w polach tekstowych. Oto przykładowe pytanie: +NW E QPMÎY NKE[ DCPFC GUKIP 2CVVGTPU! Poprawnymi odpowiedziami są „cztery” albo „4”. Mo emy utworzyć interfejs WWW, który pozwala twórcy quizu anga ować do rozpoznawania poprawnych odpowiedzi wyra enia regularne: @^EVGT[ Jednak od twórców quizów rzadko wymaga się biegłości w konstruowaniu wyra eń regularnych — są oni cenieni raczej ze względu na wiedzę ogólną. Aby uprościć im ycie, mo na więc zaimplementować przyjaźniejszy mechanizm rozpoznawania po- prawnych odpowiedzi:
  • 8. Rozdział 11. ♦ Reprezentacja i realizacja zadań 211 KPRWV GSWCNU QT KPRWV GSWCNU EVGT[ Mamy tu propozycję języka programowania obsługującego zmienne, operator o nazwie GSWCNU oraz operacje logiczne (QT czy CPF). Programiści uwielbiają nadawać nazwy swoim dziełom, nadajmy więc językowi jego miano — MarkLogic. Język miałby być łatwo rozszerzalny, bo ju oczyma wyobraźni widzimy postulaty zwiększenia jego mo liwości. Odłó my chwilowo na bok kwestię analizy leksykalnej, skupiając się na mechanizmie wykorzystania języka w czasie wykonania do generowania ocen odpo- wiedzi. Tu właśnie zastosowanie znajdzie wzorzec Interpreter. Implementacja Nasz język składa się z wyra eń (to znaczy elementów, dla których da się obliczyć wartości). Z tabeli 11.1 wynika jasno, e nawet tak prosty język jak MarkLogic musi uwzględniać wiele elementów. Tabela 11.1. Elementy gramatyki języka MarkLogic Opis Nazwa w notacji EBNF Nazwa klasy Przykład Zmienna XCTKCDNG 8CTKCDNG'ZRTGUUKQP KPRWV Literał łańcuchowy UVTKPI.KVGTCN .KVGTCN'ZRTGUUKQP EVGT[ Logiczne i CPF'ZRT $QQNGCP#PF'ZRTGUUKQP KPRWV GSWCNU CPF QVJGT GSWCNU Logiczne lub QT'ZRT $QQNGCP1T'ZRTGUUKQP KPRWV GSWCNU QT QVJGT GSWCNU Test równości GSWCNU'ZRT 'SWCNU'ZRTGUUKQP KPRWV GSWCNU W tabeli 11.1 mamy między innymi kolumnę nazw EBNF. Có to za nazwy? To nota- cja wykorzystywana do opisu gramatyki języka. EBNF to skrót od Extended Backu- sNaur Form (rozszerzona notacja Backusa-Naura). Notacja ta składa się z szeregu wierszy (zwanych regułami produkcyjnymi), w których znajduje się nazwa i opis przyjmujący postać odniesień do innych reguł produkcyjnych (ang. productions) i symboli końco- wych (ang. terminals), których nie da się ju wyrazić odwołaniami do kolejnych reguł produkcyjnych. Naszą gramatykę w notacji EBNF mo na by zapisać następująco: GZRT QRGTCPF QT'ZRT ^ CPF'ZRT
  • 9. QRGTCPF GZRT ^ UVTKPI.KVGTCN ^ XCTKCDNG GS'ZRT
  • 10. QT'ZRT QT QRGTCPF CPF'ZRT CPF QRGTCPF GSWCNU'ZRT GSWCNU QRGTCPF XCTKCDNG YQTF Niektóre z symboli mają znaczenie specjalne (znane z notacji wyra eń regularnych): na przykład gwiazdka (
  • 11. ) oznacza zero lub więcej wystąpień, a pionowa kreska (^) to to samo co w języku naturalnym „lub”. Elementy grupujemy za pośrednictwem nawia- sów. W powy szym przykładzie wyra enie (GZRT) składa się z operandu (QRGTCPF), z którym występuje zero lub więcej wyra eń logicznej sumy (QT'ZRT) bądź logicznego iloczynu (CPF'ZRT). Operand mo e być wyra eniem ujętym w nawiasy, ciągiem ogra- niczonym znakami cudzysłowu (tej reguły produkcyjnej nie ma co prawda w powy - szym przykładzie) albo zmienną (XCTKCDNG). Jeśli przyzwyczaić się do ciągłego odsyła- nia od jednej reguły produkcyjnej do kolejnej, notacja EBNF staje się całkiem poręczna.
  • 12. 212 Część III ♦ Wzorce Na rysunku 11.1 mamy prezentację elementów gramatyki w postaci klas. Rysunek 11.1. Klasy wzorca Interpreter obsługujące język MarkLogic Jak widać, klasa $QQNGCP#PF'ZRTGUUKQP i jej „rodzeństwo” dziedziczą po klasie 1RGTCVQ T'ZRTGUUKQP. Wszystkie te klasy realizują bowiem operacje na obiektach wyra eń (obiektach klasy 'ZRTGUUKQP). Klasy 8CTKCDNG'ZRTGUUKQP i .KVGTCN'ZRTGUUKQP operują wprost na wartościach. Wszystkie obiekty hierarchii 'ZRTGUUKQP implementują metodę KPVGTRTGV zdefiniowa- ną w abstrakcyjnej klasie bazowej hierarchii, czyli właśnie w klasie 'ZRTGUUKQP. Me- toda ta oczekuje przekazania w wywołaniu obiektu klasy %QPVGZV wykorzystywanego w roli wspólnego repozytorium danych. Ka dy obiekt klasy 'ZRTGUUKQP mo e składo- wać dane w obiekcie klasy %QPVGZV, który jest przekazywany pomiędzy obiektami hierarchii 'ZRTGUUKQP. Aby dało się w prosty sposób wyodrębniać dane z obiektu %QPVGZV, klasa bazowa 'ZRTGUUKQP implementuje metodę IGV-G[ zwracającą unikalny uchwyt. Zobaczmy, jak całość działa w praktyce z implementacjami abstrakcji 'ZRTGUUKQP: CDUVTCEV ENCUU 'ZRTGUUKQP ] CDUVTCEV HWPEVKQP KPVGTRTGV %QPVGZV EQPVGZV HWPEVKQP IGV-G[ ] TGVWTP UVTKPI VJKU _ _ ENCUU .KVGTCN'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ] RTKXCVG XCNWG HWPEVKQP AAEQPUVTWEV XCNWG ] VJKU XCNWG XCNWG _ HWPEVKQP KPVGTRTGV %QPVGZV EQPVGZV ] EQPVGZV TGRNCEG VJKU VJKU XCNWG _ _
  • 13. Rozdział 11. ♦ Reprezentacja i realizacja zadań 213 ENCUU %QPVGZV ] RTKXCVG GZRTGUUKQPUVQTG CTTC[ HWPEVKQP TGRNCEG 'ZRTGUUKQP GZR XCNWG ] VJKU GZRTGUUKQPUVQTG= GUR IGV-G[ ? XCNWG _ HWPEVKQP NQQMWR 'ZRTGUUKQP GZR ] TGVWTP VJKU GZRTGUUKQPUVQTG= GZR IGV-G[ ? _ _ EQPVGZV PGY %QPVGZV NKVGTCN PGY .KVGTCN'ZRTGUUKQP EVGT[ NKVGTCN KPVGTRTGV EQPVGZV RTKPV EQPVGZV NQQMWR NKVGTCN Zacznijmy od klasy %QPVGZV. Jak widać, jest ona w istocie jedynie fasadą tablicy aso- cjacyjnej reprezentowanej składową GZRTGUUKQPUVQTG i słu ącej do przechowywania danych. Metoda TGRNCEG klasy %QPVGZV przyjmuje na wejście obiekt klasy 'ZRTGUUKQP, który występuje w roli klucza tablicy asocjacyjnej, oraz wartość dowolnego typu lądu- jącą w tablicy asocjacyjnej w parze z przekazanym kluczem. Klasa udostępnia równie metodę NQQMWR umo liwiającą odczyt zapisanych w tablicy danych. Klasa 'ZRTGUUKQP definiuje abstrakcyjną metodę KPVGTRTGV i konkretną metodę IGV-G[ , która na podstawie bie ącego obiektu ( VJKU) generuje unikalną w obrębie hierarchii etykietę. Etykieta powstaje w wyniku rzutowania wartości VJKU na typ UVTKPI. Domyślny wynik konwersji obiektu na kontekst ciągu znaków to ciąg zawierający zna- kową reprezentację identyfikatora obiektu. ENCUU 2TKPV/G ]_ VGUV PGY 2TKPV/G RTKPV VGUV wydruk: 1DLGEV KF Metoda IGV-G[ czyni z tej cechy języka narzędzie generowania klucza do tabeli aso- cjacyjnej. Metoda ta jest wykorzystywana w kontekście wywołań %QPVGZVNQQMWR i %QPVGZVTGRNCEG , konwertując argumenty typu 'ZRTGUUKQP na ich reprezentację znakową. Rzutowanie obiektów na ciągi na potrzeby tablic asocjacyjnych jest użyteczne, ale nie zawsze bezpieczne. W czasie pisania tej książki język PHP5 zawsze przy okazji takiego rzutowania generował ciąg z identyfikatorem obiektu. Zdaje się jed- nak, że docelowo konwersja ta ma uwzględniać implementację metody specjalnej AAVQ5VTKPI . Oparcie wyniku konwersji na wywołaniu tej metody oznaczać będzie unieważnienie gwarancji wygenerowania unikalnego ciągu. Gwarancję tę będzie można przywrócić, jawnie implementując w klasie bazowej wykorzystywanej hierarchii metodę AAVQ5VTKPI jako metodę finalną, uniemożliwiając jej przesłanianie w kla- sach pochodnych: HKPCN HWPEVKQP AAVQ5VTKPI ] TGVWTP UVTKPI VJKU _
  • 14. 214 Część III ♦ Wzorce Klasa .KVGTCN'ZRTGUUKQP definiuje konstruktor przyjmujący wartość dowolnego ty- pu zapisywaną w składowej XCNWG. Metoda KPVGTRTGV klasy wymaga zaś przekaza- nia obiektu klasy %QPVGZV. Jej implementacja sprowadza się do wywołania metody %QPVGZVTGRNCEG z przekazaniem w wywołaniu wartości zwracanej przez metodę IGV-G[ i wartością składowej XCNWG. Schemat taki będziemy obserwować w pozo- stałych klasach wyra eń. Metoda KPVGTRTGV zawsze wypisuje wyniki swojego dzia- łania za pośrednictwem obiektu %QPVGZV. W prezentowanym kodzie nie zabrakło przykładowego kodu u ytkującego klasy kon- kretyzującego obiekty klas %QPVGZV i .KVGTCN'ZRTGUUKQP (z wartością „cztery”), a na- stępnie przekazującego obiekt %QPVGZV do wywołania .KVGTCN'ZRTGUUKQPKPVGTRTGV . Metoda ta zapisuje parę klucz-wartość w obiekcie %QPVGZV, z którego mo na ją później wyodrębnić wywołaniem NQQMWR . Zdefiniujmy pozostałe klasy symboli końcowych naszej gramatyki. Klasa 8CTKC DNG'ZRTGUUKQP jest ju nieco bardziej zło ona: ENCUU 8CTKCDNG'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ] RTKXCVG PCOG RTKXCVG XCN HWPEVKQP AAEQPUVTWEV PCOG XCNPWNN ] VJKU PCOG PCOG VJKU XCN XCN _ HWPEVKQP KPVGTRTGV %QPVGZV EQPVGZV ] KH KUAPWNN VJKU XCN ] EQPVGZV TGRNCEG VJKU VJKU XCN VJKU XCN PWNN _ _ HWPEVKQP UGV8CNWG XCNWG ] VJKU XCN XCNWG _ HWPEVKQP IGV-G[ ] TGVWTP VJKU PCOG _ _ EQPVGZV PGY %QPVGZV O[XCT PGY 8CTKCDNG'ZRTGUUKQP KPRWV EVGT[ O[XCT KPVGTRTGV EQPVGZV RTKPV EQPVGZV NQQMWR O[XCT wydruk: EVGT[ PGYXCT PGY 8CTKCDNG'ZRTGUUKQP KPRWV PGYXCT KPVGTRTGV EQPVGZV RTKPV EQPVGZV NQQMWR PGYXCT wydruk: EVGT[ O[XCT UGV8CNWG RKúè
  • 15. Rozdział 11. ♦ Reprezentacja i realizacja zadań 215 O[XCT KPVGTRTGV EQPVGZV RTKPV EQPVGZV NQQMWR O[XCT wydruk: RKúè RTKPV EQPVGZV NQQMWR PGYXCT wydruk: RKúè Klasa 8CTKCDNG'ZRTGUUKQP przyjmuje przy konstrukcji parę wartości: nazwę zmiennej i jej wartość. Udostępnia te metodę UGV8CNWG , aby u ytkownicy mogli przypisywać do zmiennych nowe wartości. Metoda KPVGTRTGV sprawdza przede wszystkim, czy składowa XCN obiektu ma war- tość niepustą. Jeśli tak, wartość ta jest zapisywana w kontekście, po czym do składowej XCN przypisywana jest wartość pusta, na wypadek, gdyby metoda KPVGTRTGV została ponownie wywołana po tym, jak inny egzemplarz 8CTKCDNG'ZRTGUUKQP o tej samej na- zwie zmienił wartość zapisaną w kontekście. W rozszerzeniach języka trzeba by prze- widzieć operowanie na obiektach 'ZRTGUUKQP, tak aby zmienna mogła zawierać wyniki testów i operacji. Na razie jednak taka implementacja 8CTKCDNG'ZRTGUUKQP jest wystar- czająca. Zauwa my, e przesłoniliśmy w niej implementację IGV-G[ , tak aby wartość klucza konstytuowana była nie identyfikatorem egzemplarza klasy, a ciągiem zapisa- nym w składowej PCOG. Wyra enia operatorów w naszym języku ka dorazowo operują na dwóch obiektach 'ZRTGUUKQP (obsługujemy bowiem wyłącznie operatory dwuargumentowe). Zasadne jest więc wyprowadzenie ich ze wspólnej klasy bazowej. Oto klasa 1RGTCVQT'ZRTGUUKQP: CDUVTCEV ENCUU QRGTCVQT'ZRTGUUKQP GZVGPFU 'ZRTGUUKQP ] RTQVGEVGF NAQR RTQVGEVGF TAQR HWPEVKQP AAEQPUVTWEV 'ZRTGUUKQP NAQR 'ZRTGUUKQP TAQR ] VJKU NAQR NAQR VJKU TAQR TAQR _ HWPEVKQP KPVGTRTGV %QPVGZV EQPVGZV ] VJKU NAQR KPVGTRTGV EQPVGZV VJKU TAQR KPVGTRTGV EQPVGZV TGUWNVAN EQPVGZV NQQMWR VJKU NAQR TGUWNVAT EQPVGZV NQQMWR VJKU TAQR VJKU FQ1RGTCVKQP EQPVGZV TGUWNVAN TGUWNVAT _ RTQVGEVGF CDUVTCEV HWPEVKQP FQ1RGTCVKQP %QPVGZV EQPVGZV TGUWNVAN TGUWNVAT _ Klasa 1RGTCVQT'ZRTGUUKQP to klasa abstrakcyjna. Implementuje co prawda metodę KPVGTRTGV , ale definiuje równie abstrakcyjną metodę FQ+PVGTRTGV . Konstruktor oczekuje przekazania dwóch obiektów klasy 'ZRTGUUKQP: NAQR i TAQR, do których referencje zapisywane są w zabezpieczonych składowych obiektu.
  • 16. 216 Część III ♦ Wzorce Implementacja metody KPVGTRTGV rozpoczyna się od wywołania KPVGTRTGV na rzecz obu operandów (jeśli pamiętasz poprzedni rozdział, zauwa ysz tu zapewne za- stosowanie wzorca Composite). Po ewaluacji operandów metoda KPVGTRTGV musi pozyskać zwracane przez nie wartości. Odwołuje się do niech za pośrednictwem me- tody %QPVGZVNQQMWR wywoływanej dla obu składowych. Dalej następuje wywołanie FQ+PVGTRTGV , o którego wyniku decyduje jednak implementacja w klasach pochodnych. Spójrzmy na jej implementację w klasie 'SWCNU'ZRTGUUKQP, porównującej dwa obiekty klasy 'ZRTGUUKQP: ENCUU 'SWCNU'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ] RTQVGEVGF HWPEVKQP FQ1RGTCVKQP %QPVGZV EQPVGZV TGUWNVAN TGUWNVAT ] EQPVGZV TGRNCEG VJKU TGUWNVAN TGUWNVAT _ _ Klasa 'SWCNU'ZRTGUUKQP implementuje jedynie metodę FQ1RGTCVKQP , w ramach której porównuje wartości operandów przekazanych z metody KPVGTRTGV klasy nadrzędnej, a wynik porównania umieszcza w przekazanym obiekcie %QPVGZV. Implementację klas wyra eń wieńczą klasy wyra eń logicznych — $QQNGCP1T'ZRTGUUKQP i $QQNGCP#PF'ZRTGUUKQP: ENCUU $QQNGCP1T'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ] RTQVGEVGF HWPEVKQP FQ1RGTCVKQP %QPVGZV TGUWNVAN TGUWNVAT ] EQPVGZV TGRNCEG VJKU TGUWNVAN ^^ TGUWNVAT _ _ ENCUU $QQNGCP#PF'ZRTGUUKQP GZVGPFU 1RGTCVQT'ZRTGUUKQP ] RTQVGEVGF HWPEVKQP FQ1RGTCVKQP %QPVGZV TGUWNVAN TGUWNVAT ] EQPVGZV TGRNCEG VJKU TGUWNVAN TGUWNVAT _ _ Zamiast sprawdzania równości aplikujemy tu operatory operacji logicznej sumy (w $QQNGCP1T'ZRTGUUKQP) bądź logicznego iloczynu ($QQNGCP#PF'ZRTGUUKQP). Wynik operacji jest przekazywany do metody %QPVGZVTGRNCEG . Mamy ju bazę kodu wystarczającą do wykonania prezentowanego wcześniej fragmentu kodu naszego minijęzyka. Oto on: KPRWV GSWCNU QT KPRWV GSWCNU EVGT[ Powy sze wyra enie mo emy odwzorować w hierarchii 'ZRTGUUKQP w sposób nastę- pujący: EQPVGZV PGY %QPVGZV KPRWV PGY 8CTKCDNG'ZRTGUUKQP KPRWV UVCVGOGPV PGY $QQNGCP1T'ZRTGUUKQP PGY 'SWCNU'ZRTGUUKQP KPRWV PGY .KVGTCN'ZRTGUUKQP EVGT[ PGY 'SWCNU'ZRTGUUKQP KPRWV PGY .KVGTCN'ZRTGUUKQP
  • 17. Rozdział 11. ♦ Reprezentacja i realizacja zadań 217 Konkretyzujemy tu zmienną o nazwie KPRWV, ale wstrzymujemy się z przypisaniem jej wartości. Następnie tworzymy obiekt wyra enia sumy logicznej $QQNGCP'ZRTGUUKQP operującego na wynikach dwóch porównań realizowanych obiektami 'SWCNU'ZRTGUUKQP. W pierwszym porównaniu uczestniczą: obiekt wyra enia wartości (8CNWG'ZRTGUUKQP) przechowywanej w KPRWV z obiektem ciągu znaków (.KVGTCN'ZRTGUUKQP) zawierają- cym ciąg „cztery”; w drugim porównywany jest ten sam obiekt wartości KPRWV z cią- giem znaków „4”. Po takim rozpracowaniu wyra enia z przykładowego wiersza kodu mo emy przystąpić do obliczenia wartości zmiennej KPRWV i uruchomienia mechanizmu oceny: HQTGCEJ CTTC[ EVGT[ CU XCN ] KPRWV UGV8CNWG XCN RTKPV XCNP UVCVGOGPV KPVGTRTGV EQPVGZV KH EQPVGZV NQQMWR UVCVGOGPV ] RTKPV PCMQOKVC QFRQYKGF PP _ GNUG ] RTKPV Q Q NGL CYMKPP _ _ Mamy tu trzykrotne uruchomienie tego samego kodu, dla trzech ró nych wartości zmiennej wejściowej. Za pierwszym razem ustawiamy tymczasową zmienną XCN na „cztery”, przypisując ją następnie do obiektu 8CTKCDNG'ZRTGUUKQP za pośrednictwem metody UGV8CNWG . Dalej wywołujemy metodę KPVGTRTGV na rzecz szczytowego obiektu 'ZRTGUUKQP (obiektu $QQNGCP1T'ZRTGUUKQP zawierającego referencję do pozo- stałych obiektów wyra eń uczestniczących w instrukcji). Spójrzmy na sposób realiza- cji tego wywołania: Obiekt UVCVGOGPV wywołuje metodę KPVGRTGV na rzecz składowej NAQR (pierwszego obiektu klasy 'SWCNU'ZRTGUUKQP). Pierwszy z obiektów 'SWCNU'ZRTGUUKQP wywołuje z kolei metodę KPVGTRTGV na rzecz swojej składowej NAQR (referencji do obiektu 8CTKCDNG'ZRTGUUKQP przechowującego wartość „cztery”). Obiekt 8CTKCDNG'ZRTGUUKQP zapisuje swoją bie ącą wartość do wskazanego obiektu klasy %QPVGZV (wywołaniem %QPVGZVTGRNCEG ). Pierwszy z obiektów 'SWCNU'ZRTGUUKQP wywołuje metodę KPVGTRTGV na rzecz swojej składowej TAQR (referencji do obiektu .KVGTCN'ZRTGUUKQP inicjowanego wartością „cztery”). Obiekt .KVGTCN'ZRTGUUKQP rejestruje właściwą dla siebie parę klucz-wartość w obiekcie kontekstu. Pierwszy z obiektów 'SWCNU'ZRTGUUKQP odczytuje wartości NAQR („cztery”) i TAQR („cztery”) z obiektu kontekstu. Pierwszy z obiektów 'SWCNU'ZRTGUUKQP porównuje odczytane w poprzednim kroku wartości i rejestruje wynik porównania (VTWG) wraz z właściwym sobie kluczem w obiekcie kontekstu.
  • 18. 218 Część III ♦ Wzorce Po powrocie w górę drzewa obiektów następuje wywołanie metody KPVGTRTGV na rzecz składowej TAQR obiektu UVCVGOGPV. Wartość tego wywołania (tym razem HCNUG) obliczana jest identycznie jak dla pierwszego obiektu NAQR. Obiekt UVCVGOGPV odczytuje wartości swoich operandów z obiektu kontekstu i porównuje je za pośrednictwem operatora ^^. Suma logiczna wartości VTWG i HCNUG daje VTWG i taka wartość jest ostatecznie składowana w obiekcie kontekstu. Cały ten proces to zaledwie pierwsza iteracja pętli. Oto wynik wykonania wszystkich trzech przebiegów: EVGT[ PCMQOKVC QFRQYKGF PCMQOKVC QFRQYKGF Q Q NGL CYMK Być mo e zrozumienie tego, co dzieje się w powy szym kodzie, wymagać będzie kil- kukrotnej lektury opisu — znów mamy bowiem do czynienia z pomieszaniem pomiędzy drzewami klas a hierarchiami obiektów. Klasy wyra eń tworzą hierarchię dziedzicze- nia 'ZRTGUUKQP, ale równocześnie obiekty tych klas są w czasie wykonania formowane w strukturę drzewiastą. Nale y jednak pamiętać o rozró nieniu obu hierarchii. Kompletny diagram klas dla tego przykładu prezentowany jest na rysunku 11.2. Ciemne strony wzorca Interpreter Po uło eniu rdzenia hierarchii klas wzorca Interpreter jego rozbudowa jest ju dość pro- sta, odbywa się jednak przez tworzenie coraz to nowych klas. Z tego względu wzorzec Interpreter najlepiej stosować do implementacji języków stosukowo uproszczonych. W obliczu potrzeby pełnoprawnego języka programowania nale ałoby raczej skorzy- stać z gotowych narzędzi przeznaczonych do analizy leksykalnej i implementacji wła- snej gramatyki. Dalej, klasy wzorca Interpreter często realizują bardzo podobne zadania, warto więc pilnować, aby nie dochodziło w nich do niepotrzebnego powielania kodu. Wiele osób, przymierzając się do pierwszego w swoim wykonaniu wdro enia wzorca Interpreter, rozczarowuje się odkryciem faktu, e wzorzec ten nie obejmuje analizy leksykalnej. Oznacza to, e nie wystarczy on do implementacji gotowego mechanizmu skryptowego rozszerzania aplikacji. Przykładowa implementacja analizy leksykalnej mocno uproszczonego języka prezentowana jest w dodatku B.
  • 19. Rozdział 11. ♦ Reprezentacja i realizacja zadań 219 Rysunek 11.2. Wdro enie wzorca Interpreter Wzorzec Strategy Klasy często obcią ane są nadmierną liczbą zadań. To zrozumiałe: niemal zawsze two- rzymy je z myślą o kilku podstawowych funkcjach. W trakcie kodowania okazuje się, e niektóre z tych funkcji trzeba zmieniać w zale ności od okoliczności. Oznacza to konieczność podziału klasy na podklasy. I zanim się ktokolwiek obejrzy, projekt zostaje rozdarty przeciwnymi nurtami. Problem Poniewa zdołaliśmy ostatnio opracować implementację miniaturowego języka oceny, trzymajmy się przykładu z quizami. Quizy nie mogą się obejść bez pytań, skonstruujemy więc klasę 3WGUVKQP (pytanie) i wyposa ymy ją w metodę oceny — OCTM . Wszystko w porządku, dopóki nie pojawi się potrzeba obsługiwania ró nych mechanizmów oceniania. Załó my, e mamy zaimplementować ocenę wedle języka MarkLogic, ocenę na pod- stawie prostego dopasowania odpowiedzi i ocenę z dopasowaniem przy u yciu wyra eń regularnych. W pierwszym podejściu moglibyśmy zró nicować projekt pod kątem tych mechanizmów oceny, jak na rysunku 11.3.
  • 20. 220 Część III ♦ Wzorce Rysunek 11.3. Definiowanie klas pochodnych wedle strategii oceny Całość będzie się sprawdzać dopóty, dopóki ocena pozostanie jedynym zmiennym aspektem hierarchii. Wyobraźmy sobie jednak, e za ądano od nas dodatkowo obsłu- gi ró nego rodzaju pytań: czysto tekstowych i opartych na materiale audiowizualnym. Powstaje problem uwzględnienia dwóch kierunków zmian w jednym drzewie dziedzi- czenia — patrz rysunek 11.4. Rysunek 11.4. Wyró nianie klas pochodnych według dwóch kryteriów podziału Nie tylko doszło do podwojenia (niemal) liczby klas w hierarchii, ale i do powielenia kodu. Nasza logika oceniania jest bowiem powielona w obu podgałęziach hierarchii dziedziczenia. Jeśli kiedykolwiek staniesz w obliczu powielania algorytmu w równoległych gałęziach hierarchii dziedziczenia (powielania tak przez wydzielanie klas pochodnych, jak i roz- budowywanie instrukcji warunkowych), powinieneś rozwa yć wyodrębnienie algorytmu do jego własnego typu.
  • 21. Rozdział 11. ♦ Reprezentacja i realizacja zadań 221 Implementacja Wzorzec Strategy (strategia), podobnie jak cała gama najlepszych wzorców, łączy prostotę z wielkimi mo liwościami. Kiedy klasy muszą obsługiwać wielorakie imple- mentacje interfejsu (u nas są to wielorakie mechanizmy oceny), wzorzec ten zakłada zaniechanie rozbudowywania oryginalnej hierarchii klas, zalecając wyodrębnienie owych implementacji do osobnego typu. Odnosząc to do naszego przykładu, powiedzielibyśmy, e najlepiej byłoby wyod- rębnić osobny typ mechanizmu oceny — /CTMGT. Nową strukturę projektu ilustruje ry- sunek 11.5. Rysunek 11.5. Wyodrębnienie algorytmów do osobnego typu To kolejny znakomity przykład wdro enia jednej z podstawowych zasad projektowych promowanych przez Bandę Czworga (i nie tylko), a mówiącej o wy szości kompozy- cji nad dziedziczeniem. Definiując i hermetyzując algorytmy oceny, redukujemy licz- bę pochodnych w hierarchii dziedziczenia i zwiększamy równocześnie elastyczność systemu. Mo emy go bowiem w dogodnych momentach uzupełniać o następne stra- tegie oceny bez konieczności wprowadzania jakichkolwiek zmian w klasach hierarchii 3WGUVKQP. Wszystkie klasy tej hierarchii mają do swojej dyspozycji egzemplarz klasy /CTMGT, a interfejs klas udostępnia metodę oceny OCTM . Szczegóły implementacji są dla wywołującego tę metodę zupełnie nieistotne. Oto hierarchia 3WGUVKQP wyra ona kodem źródłowym: CDUVTCEV ENCUU 3WGUVKQP ] RTQVGEVGF RTQORV RTQVGEVGF OCTMGT HWPEVKQP AAEQPUVTWEV RTQORV /CTMGT OCTMGT ] VJKU OCTMGT OCTMGT VJKU RTQORV RTQORV _ HWPEVKQP OCTM TGURQPUG ]
  • 22. 222 Część III ♦ Wzorce TGVWTP VJKU OCTMGT OCTM TGURQPUG _ _ ENCUU 6GZV3WGUVKQP GZVGPFU 3WGUVKQP ] operacje charakterystyczne dla prezentacji pytań w formie tekstowej… _ ENCUU #83WGUVKQP GZVGPFU 3WGUVKQP ] operacje charakterystyczne dla prezentacji pytania z materiałem audiowizualnym… _ Szczegóły implementacyjne rozró niające klasy 6GZV3WGUVKQP i #83WGUVKQP pozosta- wiłem wyobraźni Czytelnika. Najwa niejsze z naszego punktu widzenia funkcje tych klas zdefiniowane zostały bowiem w klasie bazowej 3WGUVKQP, która ponadto przecho- wuje w składowej OCTMGT obiekt oceny (obiekt klasy /CTMGT). Kiedy następuje wywo- łanie metody 3WGUVKQPOCTM z argumentem reprezentującym odpowiedź uczestnika quizu, realizacja wywołania w klasie 3WGUVKQP polega na oddelegowaniu wywołania do odpowiedniej metody obiektu /CTMGT. Zdefiniujmy klasę obiektów /CTMGT: CDUVTCEV ENCUU /CTMGT ] RTQVGEVGF VGUV HWPEVKQP AAEQPUVTWEV VGUV ] VJKU VGUV VGUV _ CDUVTCEV HWPEVKQP OCTM TGURQPUG _ ENCUU /CTM.QIKE/CTMGT GZVGPFU /CTMGT ] RTKXCVG GPIKPG HWPEVKQP AAEQPUVTWEV VGUV RCTGPVEQPUVTWEV VGUV $this-engine = new MarkParse($test); _ HWPEVKQP OCTM TGURQPUG ] return $this-engine-evaluate($response); na razie działa na niby: TGVWTP VTWG _ _ ENCUU /CVEJ/CTMGT GZVGPFU /CTMGT ] HWPEVKQP OCTM TGURQPUG ] TGVWTP VJKU VGUV TGURQPUG _ _ ENCUU 4GIGZR/CTMGT GZVGPFU /CTMGT ] HWPEVKQP OCTM TGURQPUG ] TGVWTP RTGIAOCVEJ VJKU VGUV TGURQPUG _ _
  • 23. Rozdział 11. ♦ Reprezentacja i realizacja zadań 223 W implementacji klas hierarchii /CTMGT niewiele jest elementów zaskakujących — w rzeczy samej niewiele z nich wymaga w ogóle jakiegokolwiek komentarza. Zauwa - my jedynie, e obiekty klasy /CTM.QIKE/CTMGT są przystosowane do korzystania z ana- lizatora leksykalnego, którego kod jest prezentowany w dodatku B. Jednak na potrzeby tego przykładu mo emy ten aspekt klasy pominąć, więc metoda /CTM.QIKE/CTMGTOCTM realizuje na razie ocenę „na pół gwizdka”, zwracając za ka dym razem VTWG. Najwa - niejsza w tej hierarchii jest definiowana nią struktura, nie zaś szczegóły implementacji poszczególnych strategii ocen. Struktura ta ma zaś umo liwiać przełączanie mechani- zmu oceny pomiędzy obiektami hierarchii /CTMGT bez uszczerbku dla klasy 3WGUVKQP, która się do tego mechanizmu odwołuje. Wcią pozostaje oczywiście kwestia podjęcia decyzji co do zastosowania jednego z konkretnych obiektów hierarchii /CTMGT. Problem ten rozwiązuje się w praktyce na dwa sposoby. Pierwszy polega na wyborze strategii oceny na etapie układania quizu przez jego autora, a wybór sprowadza się do zaznaczenia odpowiedniego pola w for- mularzu. Drugi sposób to rozró nianie mechanizmu oceny na podstawie struktury cią- gu określającego bazę oceny. Jeśli baza wyra ona jest prostą odpowiedzią, wybierany jest mechanizm prostego porównania-dopasowania (/CVEJ/CTMGT): RKúè Wybór mechanizmu MarkLogic sygnalizowany jest znakiem dwukropka poprzedzają- cego wyra enie oceny: KPRWV GSWCNU RKúè Z kolei ocena na podstawie dopasowania wyra enia regularnego wybierana jest w przy- padku rozpoznania w ciągu wzorca odpowiedzi znaków ukośników ograniczających wyra enie: RK Oto kod ilustrujący stosowanie poszczególnych klas: OCTMGTU CTTC[ PGY 4GIGZR/CTMGT RK PGY /CVEJ/CTMGT RKúè PGY /CTM.QIKE/CTMGT KPRWV GSWCNU RKúè HQTGCEJ OCTMGTU CU OCTMGT ] RTKPV IGVAENCUU OCTMGT P SWGUVKQP PGY 6GZV3WGUVKQP +NG DQMÎY OC RKúEKQDQM! OCTMGT HQTGCEJ CTTC[ RKúè EVGT[ CU TGURQPUG ] RTKPV VQFRQYKGF TGURQPUG KH SWGUVKQP OCTM TGURQPUG ] RTKPV Y[ OKGPKVC QFRQYKGF P _ GNUG ] RTKPV RQO[ MCP _ _ _ Konstruujemy powy ej trzy obiekty strategii oceny, z których ka dy jest następnie wy- korzystywany do konstrukcji obiektu pytania 6GZV3WGUVKQP. Następnie ka dy z takich obiektów jest konfrontowany z dwoma przykładowymi odpowiedziami.
  • 24. 224 Część III ♦ Wzorce Klasa /CTM.QIKE/CTM jest w swej obecnej postaci jedynie makietą, a jej metoda OCTM ka dorazowo zwraca wartość VTWG. Oznaczony komentarzem kod da się jednak uruchomić w połączeniu z przykładową implementacją analizatora leksykalnego prezentowaną w dodatku B; mo na te ją przystosować do współpracy z analiza- torami autorstwa osób trzecich. Oto wynik wykonania powy szego kodu: 4GIGZR/CTMGT QFRQYKGF RKúè Y[ OKGPKVC QFRQYKGF QFRQYKGF EVGT[ RQO[ MC /CVEJ/CTMGT QFRQYKGF RKúè Y[ OKGPKVC QFRQYKGF QFRQYKGF EVGT[ RQO[ MC /CTM.QIKE/CTMGT QFRQYKGF RKúè Y[ OKGPKVC QFRQYKGF QFRQYKGF EVGT[ Y[ OKGPKVC QFRQYKGF Klasa /CTM.QIKE/CTMGT jest w tej chwili jedynie atrapą. Jej metoda oceny daje zawsze wartość VTWG, przez co w powy szym kodzie obie udzielone odpowiedzi są rozpozna- wane jako poprawne. W tym przykładzie obserwowaliśmy przekazywanie konkretnych danych od u ytkow- nika (podającego na wejście wartość zmiennej TGURQPUG) do obiektu strategii oceny; przekazanie odbywało się za pośrednictwem metody 3WGUVKQPOCTM . W pewnych sytuacjach nie zawsze znana z góry jest ilość informacji wymaganych przez obiekt, na rzecz którego wywoływana jest operacja. Decyzję co do ilości i rodzaju pozyskiwanych danych mo na więc oddelegować, przekazując do obiektu strategii egzemplarz obiektu reprezentującego u ytkownika. Wtedy obiekt strategii mo e wywoływać na rzecz obiektu u ytkownika metody zwracające wymagane dane. Wzorzec Observer Znamy ju pojęcie ortogonalności jako jednej z cnót projektu. Jednym z naszych (pro- gramistów) celów powinno być konstruowanie komponentów, które mo na swobodnie zmieniać albo przenosić, a których modyfikacje nie przenoszą się na pozostałe kom- ponenty. Jeśli ka da zmiana jednego z komponentów systemu prowokuje szereg zmian w innej części systemu, programowanie zmienia się w wyszukiwanie i poprawianie błędów wprowadzanych w coraz większej liczbie. Rzecz jasna nie zawsze da się osiągnąć po ądaną ortogonalność projektu. Elementy systemu muszą przecie dysponować referencjami do pozostałych części systemu. Mo na jednak minimalizować zawiązywane w ten sposób zale ności. Obserwowali- śmy ju choćby ró ne przykłady zastosowań polimorfizmu, dzięki któremu u ytkownik musi jedynie poznać i korzysta wyłącznie z interfejsu komponentu, zaś jego właściwa implementacja pozostaje poza zakresem jego zainteresowań.
  • 25. Rozdział 11. ♦ Reprezentacja i realizacja zadań 225 W pewnych okolicznościach komponenty mo na oddalić od siebie jeszcze bardziej. Weźmy jako przykład klasę odpowiedzialną za pośredniczenie w dostępie u ytkownika do systemu: ENCUU .QIKP ] EQPUV .1)+0A75'4A70-0190 EQPUV .1)+0A9410)A2#55 EQPUV .1)+0A#%%'55 RTKXCVG UVCVWU CTTC[ HWPEVKQP JCPFNG.QIKP WUGT RCUU KR ] UYKVEJ TCPF ] ECUG VJKU UGV5VCVWU UGNH.1)+0A#%%'55 WUGT KR TGV VTWG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A9410)A2#55 WUGT KR TGV HCNUG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A75'4A70-0190 WUGT KR TGV HCNUG DTGCM _ TGVWTP TGV _ RTKXCVG HWPEVKQP UGV5VCVWU UVCVWU WUGT KR ] VJKU UVCVWU CTTC[ UVCVWU WUGT KR _ HWPEVKQP IGV5VCVWU ] TGVWTP VJKU UVCVWU _ _ Klasa ta imituje proces logowania się u ytkownika w systemie — wynik logowania określany jest losowo, na podstawie wartości wywołania funkcji TCPF . Znacznik sta- tusu u ytkownika mo e w wyniku „logowania” przyjąć wartość .1)+0A#%%'55 (przyznany dostęp do systemu), .1)+0A9410)A2#55 (niepoprawne hasło) bądź .1)+0A75'4A70-0190 (niepoprawne konto). Poniewa klasa .QIKP to stra nik systemowych skarbów, będzie cieszyć się w czasie implementacji projektu (i zapewne równie później) szczególną uwagą. Mo e się oka- zać, e w przyszłości kierownictwo działu marketingu za ąda utrzymywania w reje- strze logowania nazw domenowych u ytkowników. Łatwo będzie wprowadzić ądane uzupełnienie: HWPEVKQP JCPFNG.QIKP WUGT RCUU KR ] UYKVEJ TCPF ] ECUG VJKU UGV5VCVWU UGNH.1)+0A#%%'55 WUGT KR TGV VTWG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A9410)A2#55 WUGT KR TGV HCNUG DTGCM ECUG
  • 26. 226 Część III ♦ Wzorce VJKU UGV5VCVWU UGNH.1)+0A75'4A70-0190 WUGT KR TGV HCNUG DTGCM _ .QIIGTNQI+2 WUGT KR VJKU IGV5VCVWU TGVWTP TGV _ Nieustający w trosce o bezpieczeństwo administratorzy mogą z kolei za ądać powia- damiania o nieudanych próbach logowania. Trzeba będzie ponownie wrócić do imple- mentacji metody JCPFNG.QIKP i umieścić w jej ciele dodatkowe wywołanie: KH TGV ] 0QVKHKGTOCKN9CTPKPI WUGT KR VJKU IGV5VCVWU _ Nie mo na wykluczyć, e w nieokreślonej przyszłości sekcja rozwoju ogłosi strategicz- ne połączenie działalności z pewnym dostawcą usług internetowych i za ąda ustawiania dla pewnej grupy u ytkowników wyró niających ich ciasteczek. I tak dalej, i tak dalej. Wszystkie te ądania z osobna są proste do spełnienia, ale zawsze ich realizacja odby- wa się kosztem projektu. Klasa .QIKP niechybnie stanie się w ich wyniku klasą głębo- ko osadzoną w konkretnym systemie. Nie da się jej potem łatwo wyciągnąć z projektu i zastosować w kolejnym — trzeba będzie „obrać” jej kod z wszystkich naleciałości charakterystycznych dla systemu, w którym była osadzona. Jeśli nawet oka e się to nieskomplikowane, powrócimy do programowania opartego nie na projekcie, a na umiejętnym na wycinaniu i wklejaniu kodu. W efekcie otrzymamy zaś w dwóch ró - nych systemach dwie niepodobne ju do siebie klasy .QIKP, a ulepszenia jednej z nich będziemy próbować niezale nie wprowadzić w drugiej, a synchronizacja taka stanie się niemo liwa z powodu zbyt wielkiej ich odmienności. Có mo emy zrobić, aby zachować klasę .QIKP? Mo emy wdro yć wzorzec Observer. Implementacja Sedno wzorca Observer (obserwator) polega na rozdzieleniu elementów u ytkujących (obserwatorów) od klasy centralnej (podmiotu obserwacji). Obserwatory muszą być informowane o zdarzeniach zachodzących w podmiocie obserwacji. Równocześnie nie chcemy wprowadzać trwałych i sztywnych zale ności pomiędzy podmiotem obserwa- cji a klasami obserwatorów. Mo emy więc umo liwić obserwatorom rejestrowanie się w klasie podmiotu. W tym celu powinniśmy uzupełnić klasę .QIKP o trzy nowe metody: rejestracji (CVVCEJ ), re- zygnacji (FGVCEJ ) i powiadomienia (PQVKH[ ), przystosowując klasę do wymogów wyró niających podmioty obserwacji interfejsu (tutaj ma on nazwę 1DUGTXCDNG): KPVGTHCEG 1DUGTXCDNG ] HWPEVKQP CVVCEJ 1DUGTXGT QDUGTXGT HWPEVKQP FGVCEJ 1DUGTXGT QDUGTXGT HWPEVKQP PQVKH[ _
  • 27. Rozdział 11. ♦ Reprezentacja i realizacja zadań 227 Klasa Login… RTKXCVG QDUGTXGTU … HWPEVKQP CVVCEJ 1DUGTXGT QDUGTXGT ] VJKU QDUGTXGTU=? QDUGTXGT _ HWPEVKQP FGVCEJ 1DUGTXGT QDUGTXGT ] VJKU QDUGTXGTU CTTC[AFKHH VJKU QDUGTXGTU CTTC[ QDUGTXGT _ HWPEVKQP PQVKH[ ] HQTGCEJ VJKU QDUGTXGTU CU QDU ] QDU WRFCVG VJKU _ _ … Mamy więc klasę podmiotu utrzymującą listę obiektów-obserwatorów. Obiekty te są dodawane do listy z zewnątrz poprzez wywołanie metody CVVCEJ . Rezygnacja z ob- serwacji i usunięcie z listy następuje w wyniku wywołania metody FGVCEJ . Z kolei wywołanie metody PQVKH[ słu y jako powiadomienie obiektów obserwatorów o po- tencjalnie interesujących ich zdarzeniach. Implementacja tej metody sprowadza się do przejrzenia tablicy obiektów obserwatorów i wywołania na rzecz ka dego z nich me- tody WRFCVG . Wywołanie metody rozsyłającej powiadomienia następuje we wnętrzu klasy .QIKP, w ciele metody JCPFNG.QIKP : HWPEVKQP JCPFNG.QIKP WUGT RCUU KR ] UYKVEJ TCPF ] ECUG VJKU UGV5VCVWU UGNH.1)+0A#%%'55 WUGT KR TGV VTWG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A9410)A2#55 WUGT KR TGV HCNUG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A75'4A70-0190 WUGT KR TGV HCNUG DTGCM _ VJKU PQVKH[ TGVWTP TGV _ Zdefiniujmy interfejs klas-obserwatorów: KPVGTHCEG 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG _ Do listy obserwatorów mo na dodawać (za pośrednictwem metody CVVCEJ klasy pod- miotu obserwacji) dowolne obiekty, które implementują interfejs 1DUGTXCDNG. Utwórzmy kilka takich obiektów: ENCUU 5GEWTKV[/QPKVQT GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU
  • 28. 228 Część III ♦ Wzorce KH UVCVWU=? .QIKP.1)+0A9410)A2#55 ] wyślij wiadomość do administratora… RTKPV AA%.#55AA VY[U[ CO YKCFQOQ EK GOCKN FQ CFOKPKUVTCVQTCP _ _ _ ENCUU )GPGTCN.QIIGT GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU dodaj dane sesji logowania do rejestru… RTKPV AA%.#55AA VFQFCLú YRKU FQ TGLGUVTW NQIQYCPKCP _ _ ENCUU 2CTVPGTUJKR6QQN GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU sprawdź adres IP… jeśli adres rozpoznany, ustaw plik cookie… RTKPV AA%.#55AA VWUVCYKCO RNKM EQQMKG FNC TQRQPCPGIQ CFTGUW +2P _ _ Zauwa my, e obiekty-obserwatory mogą korzystać z przekazanego egzemplarza 1DUGTXCDNG celem pozyskania dodatkowych informacji o zdarzeniu. Klasa podmiotu ob- serwacji powinna więc przewidywać stosowne metody udostępniające dane interesu- jące obserwatorów. U nas rolę tego interfejsu pełni metoda IGV5VCVWU , za pośred- nictwem której powiadamiane obiekty-obserwatory otrzymują migawkę bie ącego stanu logowania. W obiekcie klasy .QIKP mo na rejestrować dowolne obiekty, byle tylko implementowały interfejs 1DUGTXGT: NQIKP PGY .QIKP NQIKP CVVCEJ PGY 5GEWTKV[/QPKVQT NQIKP CVVCEJ PGY )GPGTCN.QIIGT NQIKP CVVCEJ PGY 2CTVPGTUJKR6QQN Otrzymaliśmy więc elastyczne powiązanie pomiędzy klasą-podmiotem obserwacji a klasami-obserwatorami. Diagram klas odpowiedni dla omawianego przykładu pre- zentowany jest na rysunku 11.6. Poznaliśmy ju najwa niejsze elementy kodu implementującego wzorzec Observer. Dla większej przejrzystości mo emy zebrać je na wspólnym listingu: KPVGTHCEG 1DUGTXCDNG ] HWPEVKQP CVVCEJ 1DUGTXGT QDUGTXGT HWPEVKQP FGVCEJ 1DUGTXGT QDUGTXGT HWPEVKQP PQVKH[ _ ENCUU .QIKP KORNGOGPVU 1DUGTXCDNG ] RTKXCVG QDUGTXGTU CTTC[ EQPUV .1)+0A75'4A70-0190
  • 29. Rozdział 11. ♦ Reprezentacja i realizacja zadań 229 Rysunek 11.6. Klasy wzorca Observer EQPUV .1)+0A9410)A2#55 EQPUV .1)+0A#%%'55 RTKXCVG UVCVWU CTTC[ HWPEVKQP CVVCEJ 1DUGTXGT QDUGTXGT ] VJKU QDUGTXGTU=? QDUGTXGT _ HWPEVKQP FGVCEJ 1DUGTXGT QDUGTXGT ] VJKU QDUGTXGTU CTTC[AFKHH VJKU QDUGTXGTU CTTC[ QDUGTXGT _ HWPEVKQP PQVKH[ ] HQTGCEJ VJKU QDUGTXGTU CU QDU ] QDU WRFCVG VJKU _ _ HWPEVKQP JCPFNG.QIKP WUGT RCUU KR ] UYKVEJ TCPF ] ECUG VJKU UGV5VCVWU UGNH.1)+0A#%%'55 WUGT KR TGV VTWG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A9410)A2#55 WUGT KR TGV HCNUG DTGCM ECUG VJKU UGV5VCVWU UGNH.1)+0A75'4A70-0190 WUGT KR TGV HCNUG DTGCM _ VJKU PQVKH[ TGVWTP TGV _
  • 30. 230 Część III ♦ Wzorce RTKXCVG HWPEVKQP UGV5VCVWU UVCVWU WUGT KR ] VJKU UVCVWU CTTC[ UVCVWU WUGT KR _ HWPEVKQP IGV5VCVWU ] TGVWTP VJKU UVCVWU _ _ KPVGTHCEG 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG _ ENCUU 5GEWTKV[/QPKVQT GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU KH UVCVWU=? .QIKP.1)+0A9410)A2#55 ] wyślij wiadomość do administratora… RTKPV AA%.#55AA VY[U[ CO YKCFQOQ EK GOCKN FQ CFOKPKUVTCVQTCP _ _ _ ENCUU )GPGTCN.QIIGT GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU dodaj dane sesji logowania do rejestru… RTKPV AA%.#55AA FQFCLú YRKU FQ TGLGUVTW NQIQYCPKCP _ _ ENCUU 2CTVPGTUJKR6QQN GZVGPFU 1DUGTXGT ] HWPEVKQP WRFCVG 1DUGTXCDNG QDUGTXCDNG ] UVCVWU QDUGTXCDNG IGV5VCVWU sprawdź adres IP… jeśli adres rozpoznany, ustaw specjalne cookie… RTKPV AA%.#55AA WUVCYKCO RNKM EQQMKG FNC TQRQPCPGIQ CFTGUW +2P _ _ Wzorzec ten doczekał się szeregu wariacji, nie jest te wolny od wad. Po pierwsze, meto- da zwracająca stan podmiotu obserwacji (IGV5VCVWU ) nie jest opisywana w interfejsie 1DUGTXCDNG. Daje to typowi 1DUGTXCDNG nadzwyczajną elastyczność, ale równocześnie redukuje bezpieczeństwo typowania. Co się stanie, jeśli któryś z obiektów obserwato- rów odwołujących się do metody IGV5VCVWU zostanie zarejestrowany w obiekcie klasy implementującej interfejs 1DUGTXCDNG, ale nie implementującej metody IGV5VCVWU ? Có , wiadomo — dojdzie do błędu krytycznego. Jak zwykle mamy tu problem zrównowa enia elastyczności i ryzyka. Pominięcie w spe- cyfikacji interfejsu 1DUGTXCDNG daje mu elastyczność, ale nara a u ytkowników na ryzyko chybionego wywołania, jeśli obiekt obserwatora zarejestrowany zostanie w złym obiek- cie 1DUGTXCDNG. Ryzyko to mo na wyeliminować przez uzupełnienie interfejsu 1DUG TXCDNG o metodę IGV5VCVWU , ale kosztem elastyczności. Niektóre z klas podmiotów obserwacji mogą bowiem na przykład udostępniać więcej ni jedną metodę zwracają- cą status.
  • 31. Rozdział 11. ♦ Reprezentacja i realizacja zadań 231 Mo na by rozwiązać problem, przekazując w wywołaniu metody WRFCVG obiektów- obserwatorów nie egzemplarz podmiotu obserwacji, ale komplet informacji o jego stanie. Osobiście często stosuję tę metodę, jeśli mam na szybko skonstruować działa- jące rozwiązanie. W naszym przykładzie metoda WRFCVG powinna więc oczekiwać przekazania nie egzemplarza klasy .QIKP, ale znacznika statusu logowania, identyfikato- ra u ytkownika i adresu IP maszyny, z której zainicjowano próbę logowania, najlepiej w postaci tablicy. Pozwala to na wyeliminowanie jednej metody z klasy .QIKP. Z dru- giej strony, jeśli stan podmiotu obserwacji miałby być opisywany zbyt wielką liczbą danych, znacznie bardziej elastycznym rozwiązaniem byłoby jednak przekazywanie w wywołaniu WRFCVG egzemplarza .QIKP. Mo na te zablokować typ w ogóle, odmawiając w klasie .QIKP współpracy z obiektami klas innych ni wyró niona (np. .QIKP1DUGTXGT). W takim układzie nale ałoby jeszcze pomyśleć o jakichś realizowanych w czasie wykonania testach obiektów przekazywa- nych w wywołaniu metody CVVCEJ ; alternatywą byłaby zmiana (uszczegółowienie) interfejsu 1DUGTXCDNG. Mamy tu ponowne zastosowanie kompozycji w czasie wykonania celem skonstruowania elastycznego i rozszerzalnego modelu. Klasa .QIKP mo e zostać teraz łatwo wyodrębnio- na z kontekstu i przerzucona do zupełnie innego projektu, gdzie mo e współpracować z zupełnie odmiennym zestawem obserwatorów. Wzorzec Visitor Jak widzieliśmy, wiele wzorców, podą ając za zasadą wy szości kompozycji nad dzie- dziczeniem, zakłada konstruowanie struktur w czasie wykonania programu. Znakomi- tym przykładem takiego wzorca jest powszechnie stosowany wzorzec kompozycji — Composite. Tam, gdzie trzeba operować na zbiorach obiektów, niektóre z operacji mogą odwoływać się do zbiorów jako takich, ale inne mogą wymagać operowania na poszcze- gólnych komponentach zbioru. Takie operacje mo na wbudować w same komponenty — w końcu to one znajdują się na najlepszej mo liwej pozycji do ich realizacji. Podejście to nie jest jednak pozbawione wad. Nie zawsze na przykład mamy dostateczną ilość informacji o operacjach, które będą wykonywane na strukturze. Jeśli klasy są uzu- pełniane operacjami od przypadku do przypadku, ich interfejsy mogą się nadmiernie rozrosnąć. Wtedy mo na uciec się do wzorca Visitor (wizytator). Problem Wróćmy do prezentowanego w poprzednim rozdziale przykładu zastosowania wzorca kompozycji. Na potrzeby pewnej gry stworzyliśmy tam armię komponentów o ciekawej cesze zastępowalności komponentu zbiorem komponentów. Operacje były tam wbu- dowywane w same komponenty — właściwe operacje realizowane były przez obiekty składowe, do których odwoływał się obiekt-kompozyt.
  • 32. 232 Część III ♦ Wzorce ENCUU #TO[ GZVGPFU %QORQUKVG7PKV ] HWPEVKQP DQODCTF5VTGPIVJ ] TGV HQTGCEJ VJKU WPKVU CU WPKV ] TGV WPKV DQODCTF5VTGPIVJ _ TGVWTP TGV _ _ ENCUU .CUGT%CPPQP7PKV GZVGPFU 7PKV ] HWPEVKQP DQODCTF5VTGPIVJ ] TGVWTP _ _ Nie są tu problemem te operacje, które stanowią podstawowe zadania klasy kompozytu. Gorzej z operacjami pobocznymi. Weźmy choćby operację, w ramach której trzeba wykonać zrzut (w postaci tekstowej) informacji o obiektach składowych kompozytu. Operację taką mo na by włączyć do klasy 7PKV: klasa Unit HWPEVKQP VGZVWOR PWO ] TGV RCF
  • 33. PWO TGV URTKPVH ] RCF_U TGV IGVAENCUU VJKU TGV UK C TC GPKC VJKU DQODCTF5VTGPIVJ P TGVWTP TGV _ Metodę tę mo na następnie przesłonić w klasie %QORQUKVG7PKV: klasa CompositeUnit HWPEVKQP VGZVWOR PWO ] TGV RCF
  • 34. PWO TGV URTKPVH ] RCF_U TGV IGVAENCUU VJKU TGV UK C TC GPKC VJKU DQODCTF5VTGPIVJ P HQTGCEJ VJKU WPKVU CU WPKV ] TGV WPKV VGZVWOR PWO _ TGVWTP TGV _ Moglibyśmy, idąc tym tropem, utworzyć metody zliczające liczbę jednostek w kompo- zycie, zapisywania danych o składowych kompozytu w bazie danych czy te obliczania liczby jednostek aprowizacji konsumowanych codziennie przez armię. Ale czy koniecznie powinniśmy włączać tego rodzaju operacje do interfejsu kompozytu? Po co rozdymać interfejs o funkcje niekoniecznie związane z podstawowym zadaniem klasy? Odpowiedź jest prosta: postanowiliśmy zdefiniować te funkcje tu, bo z tego miejsca łatwo o dostęp do składowych kompozytu.
  • 35. Rozdział 11. ♦ Reprezentacja i realizacja zadań 233 Choć co prawda łatwość przeglądania zbioru jest jedną z podstawowych cech kompo- zytu, nie oznacza to, e dosłownie ka da operacja wymagająca przejrzenia składowych kompozytu powinna być implementowana w jego klasie i zajmować miejsce w jego interfejsie. Mamy więc kolejny cel: wykorzystać w dowolnych operacjach łatwość odwołań do komponentów kompozytu bez niepotrzebnego rozdymania jego interfejsu. Implementacja Zacznijmy od zdefiniowania w abstrakcyjnej klasie 7PKV metody CEEGRV . HWPEVKQP CEEGRV #TO[8KUKVQT XKUKVQT ] OGVJQF XKUKV IGV%NCUU VJKU XKUKVQT OGVJQF VJKU _ Jak widać, metoda CEEGRV oczekuje przekazania w wywołaniu obiektu klasy #TO[ 8KUKVQT. W języku PHP mamy mo liwość dynamicznego konstruowania nazw metod wykorzystywaną tu do realizacji dynamicznego wyboru metody do wywołania na rzecz przekazanego obiektu. Dzięki temu nie musimy implementować metody CEEGRV osobno dla ka dego węzła końcowego naszej hierarchii klas. Trzeba jedynie zdefi- niować tę samą metodę w abstrakcyjnej klasie kompozytu. HWPEVKQP CEEGRV #TO[8KUKVQT XKUKVQT ] OGVJQF XKUKV IGV%NCUU VJKU XKUKVQT OGVJQF VJKU HQTGCEJ VJKU WPKVU CU VJKUWPKV ] VJKUWPKV CEEGRV XKUKVQT _ _ Metoda ta realizuje to samo zadanie co 7PKVCEEGRV , z jednym tylko dodatkiem. Na podstawie nazwy bie ącej klasy konstruuje nazwę metody do wywołania i wywołuje ją na rzecz przekazanego obiektu klasy #TO[8KUKVQT. Jeśli więc bie ącą klasą będzie #TO[, nastąpi wywołanie klasy #TO[8KUKVQTXKUKV#TO[ ; jeśli bie ącą klasą będzie 6TQQR%CTTKGT, metoda zrealizuje wywołanie #TO[8KUKVQTXKUKV6TQQR%CTTKGT i tak dalej. Po powrocie z wywołania rozpocznie się zaś pętla przeglądająca komponenty kompozytu i wywołująca na ich rzecz ich implementację metody CEEGRV . A poniewa CEEGRV powtarza tu operacje definiowane w klasach nadrzędnych, mo emy w prosty sposób wyeliminować duplikację kodu: HWPEVKQP CEEGRV #TO[8KUKVQT XKUKVQT ] RCTGPVCEEGRV XKUKVQT HQTGCEJ VJKU WPKVU CU VJKUWPKV ] VJKUWPKV CEEGRV XKUKVQT _ _ Takie ulepszenie jest bardzo eleganckie, ale choć tutaj dało oszczędność jednego za- ledwie wiersza, odbyło się z pewną szkodą dla czytelności i przejrzystości kodu. Tak czy inaczej, metoda CEEGRV pozwala nam na dwie rzeczy:
  • 36. 234 Część III ♦ Wzorce wywoływanie metody wizytacji właściwej dla bie ącego komponentu; przekazywanie obiektu wizytatora do wszystkich komponentów bie ącego kompozytu przez wywołanie ich metod CEEGRV . Trzeba nam jeszcze zdefiniować interfejs klasy #TO[8KUKVQT. Pewne pojęcie o jego składnikach daje ju metoda CEEGRV . Otó klasa wizytatora powinna definiować wer- sje metody CEEGRV dla wszystkich konkretnych klas w hierarchii. Dzięki temu na kompozytach ró nych obiektów będzie mo na wykonywać ró ne operacje. W mojej wersji tej klasy zdefiniowałem domyślne wersje metody XKUKV wywoływane auto- matycznie, jeśli klasa implementująca nie określi własnej wersji tej operacji dla danej klasy hierarchii 7PKV. CDUVTCEV ENCUU #TO[8KUKVQT ] CDUVTCEV HWPEVKQP XKUKV 7PKV PQFG HWPEVKQP XKUKV#TEJGT #TEJGT PQFG ] VJKU XKUKV PQFG _ HWPEVKQP XKUKV%CXCNT[ %CXCNT[ PQFG ] VJKU XKUKV PQFG _ HWPEVKQP XKUKV.CUGT%CPPQP7PKV .CUGT%CPPQP7PKV PQFG ] VJKU XKUKV PQFG _ HWPEVKQP XKUKV6TQQR%CTTKGT7PKV 6TQQR%CTTKGT7PKV PQFG ] VJKU XKUKV PQFG _ HWPEVKQP XKUKV#TO[ #TO[ PQFG ] VJKU XKUKV PQFG _ _ Teraz więc problem sprowadza się do implementacji klas pochodnych #TO[8KUKVQT. Oto przykład w postaci kodu generującego zestawienie informacji o obiektach-kompozytach przeniesiony ju do klasy #TO[8KUKVQT: ENCUU 6GZVWOR#TO[8KUKVQT GZVGPFU #TO[8KUKVQT ] RTKXCVG VGZV HWPEVKQP XKUKV 7PKV PQFG ] TGV RCF
  • 37. PQFG IGVGRVJ TGV URTKPVH ] RCF_U TGV IGVAENCUU PQFG TGV UK C TC GPKC PQFG DQODCTF5VTGPIVJ P VJKU VGZV TGV _ HWPEVKQP IGV6GZV ] TGVWTP VJKU VGZV _ _
  • 38. Rozdział 11. ♦ Reprezentacja i realizacja zadań 235 Spójrzmy, jak stosować taki kod: OCKPACTO[ PGY #TO[ OCKPACTO[ CFF7PKV PGY #TEJGT OCKPACTO[ CFF7PKV PGY .CUGT%CPPQP7PKV OCKPACTO[ CFF7PKV PGY %CXCNT[ VGZFWOR PGY 6GZVWOR#TO[8KUKVQT OCKPACTO[ CEEGRV VGZVFWOR RTKPV VGZVFWOR IGV6GZV Powy szy kod powinien dać następujący rezultat: #TO[ UK C TC GPKC #TEJGT UK C TC GPKC .CUGT%CPPQP7PKV UK C TC GPKC %CXCNT[ UK C TC GPKC Utworzyliśmy obiekt klasy #TO[. Poniewa jest to kompozyt, włączyliśmy do niego (za pomocą metody CFF7PKV ) pewną liczbę utworzonych specjalnie w tym celu obiektów klasy 7PKV. Następnie utworzyliśmy obiekt klasy 6GZVWOR#TO[8KUKVQT i przekazaliśmy go w wywołaniu metody #TO[CEEGRV . Metoda ta skonstruowała na podstawie nazwy klasy przekazanego obiektu nazwę metody do wywołania i wywołała metodę 6GZVWO R#TO[8KUKVQTXKUKV#TO[ . Poniewa nie przewidzieliśmy specjalnej obsługi wy- wołania XKUKV dla obiektów klasy #TO[, wywołanie to zostanie zrealizowane domyślną wersją metody XKUKV dla obiektów tego typu. W wywołaniu XKUKV przekazywana jest referencja obiektu klasy #TO[, a w samej metodzie następują wywołania metod tego obiektu (w tym nowej metody IGVGRVJ , informującej o bie ącym zagłębieniu w drzewie kompozytu), generując za ich pośrednictwem zestawienie opisujące kom- pozyt. Aby zestawienie było kompletne, metoda #TO[CEEGRV wywołuje następnie metody CEEGRV komponentów, przekazując w wywołaniu ten sam obiekt wizytatora, który sama otrzymała. W ten sposób klasa #TO[8KUKVQT „odwiedza” wszystkie obiekty wchodzące w skład drzewa kompozytu. Uzupełniając istniejący szkielet klas o kilka zaledwie metod, utworzyliśmy mechanizm, za pośrednictwem którego mo na dołączać do klasy kompozytu nowe funkcje, nie in- gerując równocześnie w interfejs kompozytu i unikając powielania kodu przeglądania komponentów. Załó my teraz, e na niektórych polach planszy jednostki muszą uiszczać myto. Pobor- ca odwiedza wtedy poszczególne jednostki armii, przy czym ró ne jednostki są ró nie opodatkowane. Na tym przykładzie dobrze będzie widać zalety specjalizowania metod klasy wizytatora: ENCUU 6CZ%QNNGEVKQP8KUKVQT GZVGPFU #TO[8KUKVQT ] RTKXCVG FWG RTKXCVG TGRQTV HWPEVKQP XKUKV 7PKV PQFG ] VJKU NGX[ PQFG _ HWPEVKQP XKUKV#TEJGT #TEJGT PQFG ] VJKU NGX[ PQFG _
  • 39. 236 Część III ♦ Wzorce HWPEVKQP XKUKV%CXCNT[ %CXCNT[ PQFG ] VJKU NGX[ PQFG _ HWPEVKQP XKUKV6TQQR%CTTKGT7PKV 6TQQR%CTTKGT7PKV PQFG ] VJKU NGX[ PQFG _ RTKXCVG HWPEVKQP NGX[ 7PKV WPKV COQWPV ] VJKU TGRQTV /[VQ PCNG PG C IGV%NCUU WPKV VJKU TGRQTV COQWPVP VJKU FWG COQWPV _ HWPEVKQP IGV4GRQTV ] TGVWTP VJKU TGRQTV _ HWPEVKQP IGV6CZ ] TGVWTP VJKU FWG _ _ W tym prostym przykładzie nie skorzystamy wprost z obiektu klasy 7PKV przekazywa- nego do ró nych metod wizytacji. Korzystamy jedynie ze specjalizacji (podziału na klasy obiektów odwiedzanych), ustalając dla ró nych klas jednostek ró ne stawki myta. Oto jak wygląda pobieranie myta z punktu widzenia u ytkownika hierarchii: OCKPACTO[ PGY #TO[ OCKPACTO[ CFF7PKV PGY #TEJGT OCKPACTO[ CFF7PKV PGY .CUGT%CPPQP7PKV OCKPACTO[ CFF7PKV PGY %CXCNT[ VCZEQNNGEVQT PGY 6CZ%QNNGEVQT8KUKVQT OCKPACTO[ CEEGRV VCZEQNNGEVQT RTKPV ä%0+' RTKPV VCZEQNNGEVQT IGV6CZ P Tak jak poprzednio, do metody CEEGRV wywołanej na rzecz obiektu klasy #TO[ prze- kazany został obiekt wizytatora — tutaj 6CZ%QNNGEVQT8KUKVQT. Ponownie te obiekt klasy #TO[ przekazuje referencję do samego siebie do metody XKUKV#TO[ , tu przed oddelegowaniem wywołania do metod CEEGRV swoich komponentów. Komponenty są nieświadome operacji przeprowadzonych w ramach wizytacji. Ograniczają się do współpracy z publicznym interfejsem wizytatora, przekazując się po kolei do metody wizytacji właściwej dla swojego typu, w ramach której następuje obliczenie nale ne- go myta. Poza metodami zdefiniowanymi w klasie bazowej hierarchii wizytatorów klasa 6CZ%QNNGEVQT8KUKVCVQT definiuje dwie metody dodatkowe: IGV4GRQTV i IGV6CZ . Ich wywołania zwracają dane zebrane podczas wizytacji: /[VQ PCNG PG C #TO[ /[VQ PCNG PG C #TEJGT /[VQ PCNG PG C .CUGT%CPPQP7PKV /[VQ PCNG PG C %CXCNT[ ä%0+'
  • 40. Rozdział 11. ♦ Reprezentacja i realizacja zadań 237 Uczestników operacji prezentowanych w przykładzie ilustruje diagram z rysunku 11.7. Rysunek 11.7. Wzorzec Visitor Wady wzorca Visitor Wzorzec Visitor to kolejny wzorzec łączący prostotę z efektywnością. Zalety nie mogą jednak przesłonić całkowicie wad wzorca, gdy i te istnieją. Po pierwsze, choć najlepiej dopasowany do wzorca kompozycji, wizytator mo e być stosowany odnośnie dowolnych kolekcji obiektów. Da się więc na przykład zaimple- mentować wizytację list obiektów, w której ka dy z obiektów przechowuje referencję swoich sąsiadów. Wyodrębniając operacje na kolekcji poza nią samą, sprzeciwiamy się jednak hermety- zacji. Otó mo e się okazać, e aby wizytator mógł w jakikolwiek u yteczny sposób przetworzyć obiekty kolekcji, będą one musiały udostępniać na zewnątrz swoje aspekty wewnętrzne (prywatne). Widać to było ju choćby w pierwszym przykładzie z tego podrozdziału, kiedy to na potrzeby klasy wizytatora 6GZVWOR#TO[8KUKVQT trzeba było uzupełnić interfejs 7PKV o dodatkową metodę. Poniewa wzorzec ten zakłada równie oddzielenie iteracji od operacji wykonywanych na komponentach kolekcji, trzeba zrzec się pewnej części kontroli — nie da się na przykład łatwo utworzyć metody wizytacji XKUKV , która wykonuje pewne operacje tak przed, jak i po odwiedzeniu komponentów zagnie d onych w kolekcji. Mo na by tę niedogodność wyeliminować, przenosząc odpowiedzialność za iterację do samych obiektów wizytatorów. Tyle e wtedy w obiektach tych dojdzie niechybnie do powie- lenia kodu iteracji. Osobiście preferuję więc obsługę iteracji w ramach klas wizytowanych, choć nie przeczę, e jej wysunięcie poza te klasy dałoby pewną zasadniczą zaletę: mo na wtedy zmieniać w poszczególnych wizytatorach sposób wizytacji.
  • 41. 238 Część III ♦ Wzorce Wzorzec Command Ostatnimi laty rzadko kiedy udawało mi się zakończyć projekt aplikacji WWW bez wdra ania w nim wzorca Command, czyli wzorca polecenia. Obiekty poleceń, choć pierwotnie stosowane w kontekście projektu graficznego interfejsu u ytkownika, spraw- dzają się równie w projektach aplikacji korporacyjnych, wymuszając separację pomię- dzy warstwą kontroli ądań (kodem obsługi i rozprowadzania ądań) a warstwą lo- giczną aplikacji. Problem Wszystkie systemy muszą podejmować decyzje o sposobie reagowania na ądania u ytkowników. W PHP proces podejmowania decyzji jest często rozproszony pomię- dzy wieloma formularzami-stronami tworzącymi interfejs aplikacji. Wybór funkcji i interfejsu odbywa się tutaj przez wybór jednej ze stron witryny WWW, np. feedback. php. Ostatnio programiści PHP optują jednak coraz silniej za podejściem, w którym wyró nione jest tylko jedno miejsce styku (patrz te następny rozdział). Tak czy inaczej, odbiorca ądania musi je oddelegować do warstwy bli szej samej logice aplikacji. Owa delegacja jest szczególnie istotna, kiedy u ytkownik mo e inicjować ądania za po- średnictwem ró nych stron WWW. Bez delegacji projekt zostałby w nieunikniony spo- sób obcią ony powieleniem kodu obsługi ądania. Wyobraźmy sobie więc projekt, w ramach którego powinniśmy realizować pewną licz- bę zadań. W szczególności system nasz powinien pozwalać wybranym u ytkownikom na zalogowanie się, a innym na przesłanie formularza zwrotnego. Do obsługi tych zadań moglibyśmy wyznaczyć strony login.php i feedback.php, konkretyzując w nich specjalizowane klasy realizujące ądania. Niestety, perspektywy systemu dla ró nych u ytkowników rzadko pokrywają się dokładnie z zadaniami, które system ma realizo- wać. Mo e się więc okazać, e na ka dej stronie potrzebujemy zarówno mo liwości logowania, jak i przesłania informacji zwrotnej. Jeśli zaś strony mają obsługiwać ró ne zadania, to mo e powinniśmy oprzeć hermetyzację właśnie na zadaniach. W ten spo- sób ułatwimy sobie uzupełnianie funkcjonalności systemu o nowe zadania i stworzymy wyraźną granicę pomiędzy warstwami systemu. W ten sposób dojdziemy do wdro e- nia wzorca Command. Implementacja Interfejs obiektu polecenia jest tak prosty jak to mo liwe — składa się w najprostszym wydaniu z jednej tylko metody — GZGEWVG . Na rysunku 11.8 %QOOCPF jest klasą abstrakcyjną. Przy tym poziomie uproszczenia mógłby zostać równie dobrze zdefiniowany jako interfejs. Osobiście skłaniam się do stosowania abstrakcji w miejsce interfejsów dlatego, e niejednokrotnie okazuje się, e w abstrak- cyjnej klasie bazowej mo na upchnąć parę funkcji wspólnych dla wszystkich obiektów pochodnych.