Darmowy fragment publikacji:
IDZ DO
IDZ DO
PRZYK£ADOWY ROZDZIA£
PRZYK£ADOWY ROZDZIA£
SPIS TREĎCI
SPIS TREĎCI
KATALOG KSI¥¯EK
KATALOG KSI¥¯EK
KATALOG ONLINE
KATALOG ONLINE
ZAMÓW DRUKOWANY KATALOG
ZAMÓW DRUKOWANY KATALOG
TWÓJ KOSZYK
TWÓJ KOSZYK
DODAJ DO KOSZYKA
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
CENNIK I INFORMACJE
ZAMÓW INFORMACJE
ZAMÓW INFORMACJE
O NOWOĎCIACH
O NOWOĎCIACH
ZAMÓW CENNIK
ZAMÓW CENNIK
CZYTELNIA
CZYTELNIA
FRAGMENTY KSI¥¯EK ONLINE
FRAGMENTY KSI¥¯EK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
PHP5. Obiekty,
wzorce, narzêdzia
Autor: Matt Zandstra
T³umaczenie: Przemys³aw Szeremiota
ISBN: 83-7361-868-6
Tytu³ orygina³u: PHP 5 Objects, Patterns, and Practice
Format: B5, stron: 464
Profesjonalne techniki programowania obiektowego w PHP5
• Poznaj zasady projektowania i programowania obiektowego
• Zastosuj wzorce projektowe podczas tworzenia aplikacji
• Wykorzystaj narzêdzia wspomagaj¹ce pracê programisty PHP5
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
i fora dyskusyjne, ale równie¿ rozbudowane aplikacje sieciowe, wykorzystywane czêsto
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
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
obiektowych w kontekġcie zastosowania ich podczas tworzenia aplikacji w PHP5.
Zawiera przegl¹d podstawowych i zaawansowanych cech PHP5 zwi¹zanych
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
• Generowanie dokumentacji za pomoc¹ PHPDocumentor
• Zarz¹dzanie wersjami plików w systemie CVS
• Tworzenie pakietów instalacyjnych
Przekonaj siê, jak potê¿nym narzêdziem jest najnowsza wersja jêzyka PHP
Spis treści
O Autorze .......................................................................................... 9
O Recenzencie Technicznym ............................................................ 10
Przedmowa ...................................................................................... 11
Część I Wprowadzenie ...................................................r............13
Rozdział 1. PHP — projektowanie i zarządzanie ................................................. 15
Problem ...................................................1...................................................1.................... 15
PHP a inne języki programowania ...................................................1.............................. 17
O książce ...................................................1...................................................1.................. 19
Podsumowanie ...................................................1...................................................1......... 21
Część II Obiekty ...................................................r......................23
Rozdział 2. PHP a obiekty ................................................................................. 25
Nieoczekiwany sukces obiektów w PHP ...................................................1..................... 25
Debata obiektowa — za czy przeciw? ...................................................1......................... 28
Podsumowanie ...................................................1...................................................1......... 29
Rozdział 3. Obiektowy elementarz ...................................................................... 31
Klasy i obiekty ...................................................1...................................................1.........31
Definiowanie składowych klasy ...................................................1.................................. 33
Metody ...................................................1...................................................1..................... 36
Typy argumentów metod ...................................................1............................................. 39
Dziedziczenie ...................................................1...................................................1...........44
Podsumowanie ...................................................1...................................................1......... 58
Rozdział 4. Zaawansowana obsługa obiektów .................................................... 59
Metody i składowe statyczne ...................................................1....................................... 59
Składowe stałe ...................................................1...................................................1..........63
Klasy abstrakcyjne ...................................................1...................................................1... 63
Interfejsy ...................................................1...................................................1.................. 66
Obsługa błędów ...................................................1...................................................1........ 68
Klasy i metody finalne ...................................................1................................................ 75
Przechwytywanie chybionych wywołań ...................................................1...................... 76
Definiowanie destruktorów ...................................................1......................................... 80
6
PHP5. Obiekty, wzorce, narzędzia
Wykonywanie kopii obiektów ...................................................1..................................... 81
Reprezentacja obiektu w ciągach znaków ...................................................1................... 84
Podsumowanie ...................................................1...................................................1......... 85
Rozdział 5. Narzędzia obiektowe ........................................................................ 87
PHP a pakiety ...................................................1...................................................1...........87
Klasy i funkcje pomocnicze ...................................................1........................................ 92
Reflection API ...................................................1...................................................1..........99
Podsumowanie ...................................................1...................................................1....... 110
Rozdział 6. Obiekty a projektowanie ................................................................ 111
Jak rozumieć projektowanie? ...................................................1.................................... 111
Programowanie obiektowe i proceduralne ...................................................1................ 112
Zasięg klas ...................................................1...................................................1.............. 117
Polimorfizm ...................................................1...................................................1............ 119
Hermetyzacja ...................................................1...................................................1.......... 120
Nieważne jak ...................................................1...................................................1.......... 122
Cztery drogowskazy ...................................................1.................................................. 123
Język UML ...................................................1...................................................1............. 124
Podsumowanie ...................................................1...................................................1....... 133
Część III Wzorce ...................................................r....................135
Rozdział 7. Czym są wzorce projektowe? Do czego się przydają? ..................... 137
Czym są wzorce projektowe? ...................................................1.................................... 137
Wzorzec projektowy ...................................................1.................................................. 139
Format wzorca według Bandy Czworga ...................................................1.................... 141
Po co nam wzorce projektowe? ...................................................1................................. 142
Wzorce projektowe a PHP ..................................................1.......................................... 144
Podsumowanie ...................................................1...................................................1....... 145
Rozdział 8. Wybrane prawidła wzorców ............................................................ 147
Olśnienie wzorcami ...................................................1...................................................1 147
Kompozycja i dziedziczenie ...................................................1...................................... 148
Rozprzęganie ...................................................1...................................................1.......... 153
Kod ma używać interfejsów, nie implementacji ...................................................1........ 156
Zmienne koncepcje ..................................................1...................................................1.. 157
Nadmiar wzorców ...................................................1...................................................1.. 158
Wzorce ...................................................1...................................................1................... 159
Podsumowanie ...................................................1...................................................1....... 160
Rozdział 9. Generowanie obiektów ................................................................... 161
Generowanie obiektów — problemy i rozwiązania ...................................................1... 161
Wzorzec Singleton ...................................................1...................................................1. 165
Wzorzec Factory Method ...................................................1.......................................... 169
Wzorzec Abstract Factory ...................................................1......................................... 174
Prototyp ...................................................1...................................................1.................. 179
Ależ to oszustwo! ...................................................1...................................................1... 183
Podsumowanie ...................................................1...................................................1....... 185
Rozdział 10. Relacje między obiektami .............................................................. 187
Strukturalizacja klas pod kątem elastyczności obiektów .............................................. 187
Wzorzec Composite ...................................................1.................................................. 188
Wzorzec Decorator ...................................................1...................................................1. 198
Wzorzec Facade ...................................................1...................................................1..... 205
Podsumowanie ...................................................1...................................................1....... 208
Spis treści
7
Rozdział 11. Reprezentacja i realizacja zadań .................................................... 209
Wzorzec Interpreter ...................................................1...................................................1 209
Wzorzec Strategy ...................................................1...................................................1... 219
Wzorzec Observer ...................................................1...................................................1.. 224
Wzorzec Visitor ..................................................1...................................................1....... 231
Wzorzec Command ...................................................1...................................................1 238
Podsumowanie ...................................................1...................................................1....... 242
Rozdział 12. Wzorce korporacyjne ..................................................................... 245
Wprowadzenie ...................................................1...................................................1........ 245
Małe oszustwo na samym początku ...................................................1.......................... 248
Warstwa prezentacji ...................................................1.................................................. 257
Warstwa logiki biznesowej ...................................................1........................................ 287
Warstwa danych ...................................................1...................................................1..... 295
Podsumowanie ...................................................1...................................................1....... 317
Część IV Narzędzia ...................................................r.................319
Rozdział 13. Dobre (i złe) praktyki ..................................................................... 321
Nie tylko kod ...................................................1...................................................1.......... 321
Pukanie do otwartych drzwi ...................................................1...................................... 322
Jak to zgrać? ...................................................1...................................................1...........324
Uskrzydlanie kodu ...................................................1...................................................1.. 325
Dokumentacja ...................................................1...................................................1......... 326
Testowanie ...................................................1...................................................1............. 328
Podsumowanie ...................................................1...................................................1....... 336
Rozdział 14. PEAR ............................................................................................ 337
Czym jest PEAR? ...................................................1...................................................1... 338
Instalowanie pakietu z repozytorium PEAR ...................................................1.............. 338
Korzystanie z pakietu PEAR ...................................................1..................................... 340
Instalator pakietu PEAR ...................................................1............................................ 343
Podsumowanie ...................................................1...................................................1....... 352
Rozdział 15. Generowanie dokumentacji — phpDocumentor .............................. 353
Po co nam dokumentacja? ...................................................1......................................... 354
Instalacja ...................................................1...................................................1................ 355
Generowanie dokumentacji ...................................................1....................................... 355
Komentarze DocBlock ...................................................1.............................................. 357
Dokumentowanie klas ...................................................1............................................... 358
Dokumentowanie plików ..................................................1............................................ 360
Dokumentowanie składowych ...................................................1................................... 360
Dokumentowanie metod ...................................................1............................................ 361
Tworzenie odnośników w dokumentacji ...................................................1................... 363
Podsumowanie ...................................................1...................................................1....... 365
Rozdział 16. Zarządzanie wersjami projektu z CVS ............................................ 367
Po co nam CVS? ...................................................1...................................................1.... 367
Skąd wziąć CVS? ...................................................1...................................................1... 368
Konfigurowanie repozytorium CVS ...................................................1.......................... 369
Rozpoczynamy projekt ...................................................1.............................................. 372
Aktualizacja i zatwierdzanie ...................................................1...................................... 374
Dodawanie i usuwanie plików i katalogów ...................................................1............... 377
Etykietowanie i eksportowanie wydania ...................................................1..................... 381
Rozgałęzianie projektu ...................................................1.............................................. 383
Podsumowanie ...................................................1...................................................1....... 386
8
PHP5. Obiekty, wzorce, narzędzia
Rozdział 17. Automatyzacja instalacji z Phing .................................................... 389
Czym jest Phing? ...................................................1...................................................1.... 390
Pobieranie i instalacja pakietu Phing ...................................................1......................... 391
Plik kompilacji — build.xml ...................................................1..................................... 391
Podsumowanie ...................................................1...................................................1....... 409
Część V Konkluzje ...................................................r.................411
Rozdział 18. Obiekty, wzorce, narzędzia ............................................................. 413
Obiekty ...................................................1...................................................1................... 413
Wzorce ...................................................1...................................................1................... 417
Narzędzia ...................................................1...................................................1................ 420
Podsumowanie ...................................................1...................................................1....... 424
Dodatki ...................................................r...................................425
Dodatek A Bibliografia .................................................................................... 427
Książki ...........................................1...................................................1............................ 427
Publikacje ...................................................1...................................................1............... 428
Witryny WWW ...................................................1...................................................1...... 428
Dodatek B Prosty analizator leksykalny ........................................................... 429
Skaner ...................................................1...................................................1..................... 429
Analizator leksykalny ...................................................1................................................ 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:
HQTOAKPRWVRTKPVHKNGAIGVAEQPVGPVU
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:
+NWE\đQPMÎYNKE\[DCPFC GUKIP2CVVGTPU!
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:
@^E\VGT[
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
KPRWVGSWCNUQTKPRWVGSWCNUE\VGT[
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
Zmienna
Literał łańcuchowy
Logiczne i
Logiczne lub
Nazwa w notacji EBNF
Nazwa klasy
Przykład
XCTKCDNG
8CTKCDNG ZRTGUUKQP
KPRWV
UVTKPI.KVGTCN
.KVGTCN ZRTGUUKQP
E\VGT[
CPF ZRT
QT ZRT
$QQNGCP#PF ZRTGUUKQP
$QQNGCP1T ZRTGUUKQP
Test równości
GSWCNU ZRT
SWCNU ZRTGUUKQP
KPRWVGSWCNU
CPFQVJGTGSWCNU
KPRWVGSWCNU
QTQVJGTGSWCNU
KPRWVGSWCNU
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:
GZRTQRGTCPF
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:
CDUVTCEVENCUU ZRTGUUKQP]
CDUVTCEVHWPEVKQPKPVGTRTGV
QPVGZVEQPVGZV
HWPEVKQPIGV-G[
]
TGVWTP
UVTKPIVJKU
_
_
ENCUU.KVGTCN ZRTGUUKQPGZVGPFU ZRTGUUKQP]
RTKXCVGXCNWG
HWPEVKQPAAEQPUVTWEV
XCNWG]
VJKU XCNWGXCNWG
_
HWPEVKQPKPVGTRTGV
QPVGZVEQPVGZV]
EQPVGZV TGRNCEG
VJKUVJKU XCNWG
_
_
Rozdział 11. ♦ Reprezentacja i realizacja zadań
213
ENCUU QPVGZV]
RTKXCVGGZRTGUUKQPUVQTGCTTC[
HWPEVKQPTGRNCEG
ZRTGUUKQPGZRXCNWG]
VJKU GZRTGUUKQPUVQTG=GUR IGV-G[
?XCNWG
_
HWPEVKQPNQQMWR
ZRTGUUKQPGZR]
TGVWTPVJKU GZRTGUUKQPUVQTG=GZR IGV-G[
?
_
_
EQPVGZVPGY QPVGZV
NKVGTCNPGY.KVGTCN ZRTGUUKQP
E\VGT[
NKVGTCN KPVGTRTGV
EQPVGZV
RTKPVEQPVGZV 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.
ENCUU2TKPV/G]_
VGUVPGY2TKPV/G
RTKPVVGUV
wydruk:
1DLGEVKF
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:
HKPCNHWPEVKQPAAVQ5VTKPI
]
TGVWTP
UVTKPIVJKU
_
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:
ENCUU8CTKCDNG ZRTGUUKQPGZVGPFU ZRTGUUKQP]
RTKXCVGPCOG
RTKXCVGXCN
HWPEVKQPAAEQPUVTWEV
PCOGXCNPWNN]
VJKU PCOGPCOG
VJKU XCNXCN
_
HWPEVKQPKPVGTRTGV
QPVGZVEQPVGZV]
KH
KUAPWNN
VJKU XCN]
EQPVGZV TGRNCEG
VJKUVJKU XCN
VJKU XCNPWNN
_
_
HWPEVKQPUGV8CNWG
XCNWG]
VJKU XCNXCNWG
_
HWPEVKQPIGV-G[
]
TGVWTPVJKU PCOG
_
_
EQPVGZVPGY QPVGZV
O[XCTPGY8CTKCDNG ZRTGUUKQP
KPRWV E\VGT[
O[XCT KPVGTRTGV
EQPVGZV
RTKPVEQPVGZV NQQMWR
O[XCT
wydruk:
E\VGT[
PGYXCTPGY8CTKCDNG ZRTGUUKQP
KPRWV
PGYXCT KPVGTRTGV
EQPVGZV
RTKPVEQPVGZV NQQMWR
PGYXCT
wydruk:
E\VGT[
O[XCT UGV8CNWG
RKúè
Rozdział 11. ♦ Reprezentacja i realizacja zadań
215
O[XCT KPVGTRTGV
EQPVGZV
RTKPVEQPVGZV NQQMWR
O[XCT
wydruk:
RKúè
RTKPVEQPVGZV 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:
CDUVTCEVENCUUQRGTCVQT ZRTGUUKQPGZVGPFU ZRTGUUKQP]
RTQVGEVGFNAQR
RTQVGEVGFTAQR
HWPEVKQPAAEQPUVTWEV
ZRTGUUKQPNAQR ZRTGUUKQPTAQR]
VJKU NAQRNAQR
VJKU TAQRTAQR
_
HWPEVKQPKPVGTRTGV
QPVGZVEQPVGZV]
VJKU NAQR KPVGTRTGV
EQPVGZV
VJKU TAQR KPVGTRTGV
EQPVGZV
TGUWNVANEQPVGZV NQQMWR
VJKU NAQR
TGUWNVATEQPVGZV NQQMWR
VJKU TAQR
VJKU FQ1RGTCVKQP
EQPVGZVTGUWNVANTGUWNVAT
_
RTQVGEVGFCDUVTCEVHWPEVKQPFQ1RGTCVKQP
QPVGZVEQPVGZV
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 ZRTGUUKQPGZVGPFU1RGTCVQT ZRTGUUKQP]
RTQVGEVGFHWPEVKQPFQ1RGTCVKQP
QPVGZVEQPVGZVTGUWNVANTGUWNVAT]
EQPVGZV TGRNCEG
VJKUTGUWNVANTGUWNVAT
_
_
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 ZRTGUUKQPGZVGPFU1RGTCVQT ZRTGUUKQP]
RTQVGEVGFHWPEVKQPFQ1RGTCVKQP
QPVGZVTGUWNVANTGUWNVAT]
EQPVGZV TGRNCEG
VJKUTGUWNVAN^^TGUWNVAT
_
_
ENCUU$QQNGCP#PF ZRTGUUKQPGZVGPFU1RGTCVQT ZRTGUUKQP]
RTQVGEVGFHWPEVKQPFQ1RGTCVKQP
QPVGZVTGUWNVANTGUWNVAT]
EQPVGZV TGRNCEG
VJKUTGUWNVANTGUWNVAT
_
_
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:
KPRWVGSWCNUQTKPRWVGSWCNUE\VGT[
Powyższe wyrażenie możemy odwzorować w hierarchii ZRTGUUKQP w sposób nastę-
pujący:
EQPVGZVPGY QPVGZV
KPRWVPGY8CTKCDNG ZRTGUUKQP
KPRWV
UVCVGOGPVPGY$QQNGCP1T ZRTGUUKQP
PGY SWCNU ZRTGUUKQP
KPRWVPGY.KVGTCN ZRTGUUKQP
E\VGT[
PGY SWCNU ZRTGUUKQP
KPRWVPGY.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[
E\VGT[CUXCN]
KPRWV UGV8CNWG
XCN
RTKPVXCN P
UVCVGOGPV KPVGTRTGV
EQPVGZV
KH
EQPVGZV NQQMWR
UVCVGOGPV]
RTKPV PCMQOKVCQFRQYKGFļ P P
_GNUG]
RTKPV QQħNGLđCYMK P P
_
_
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:
E\VGT[
PCMQOKVCQFRQYKGFļ
PCMQOKVCQFRQYKGFļ
QQħ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
Rysunek 11.3.
Definiowanie
klas pochodnych
wedle strategii oceny
Część III ♦ Wzorce
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:
CDUVTCEVENCUU3WGUVKQP]
RTQVGEVGFRTQORV
RTQVGEVGFOCTMGT
HWPEVKQPAAEQPUVTWEV
RTQORV/CTMGTOCTMGT]
VJKU OCTMGTOCTMGT
VJKU RTQORVRTQORV
_
HWPEVKQPOCTM
TGURQPUG]
222
Część III ♦ Wzorce
TGVWTPVJKU OCTMGT OCTM
TGURQPUG
_
_
ENCUU6GZV3WGUVKQPGZVGPFU3WGUVKQP]
operacje charakterystyczne dla prezentacji pytań w formie tekstowej…
_
ENCUU#83WGUVKQPGZVGPFU3WGUVKQP]
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:
CDUVTCEVENCUU/CTMGT]
RTQVGEVGFVGUV
HWPEVKQPAAEQPUVTWEV
VGUV]
VJKU VGUVVGUV
_
CDUVTCEVHWPEVKQPOCTM
TGURQPUG
_
ENCUU/CTM.QIKE/CTMGTGZVGPFU/CTMGT]
RTKXCVGGPIKPG
HWPEVKQPAAEQPUVTWEV
VGUV
RCTGPVEQPUVTWEV
VGUV
$this- engine = new MarkParse($test);
_
HWPEVKQPOCTM
TGURQPUG]
return $this- engine- evaluate($response);
na razie działa na niby :
TGVWTPVTWG
_
_
ENCUU/CVEJ/CTMGTGZVGPFU/CTMGT]
HWPEVKQPOCTM
TGURQPUG]
TGVWTP
VJKU VGUVTGURQPUG
_
_
ENCUU4GIGZR/CTMGTGZVGPFU/CTMGT]
HWPEVKQPOCTM
TGURQPUG]
TGVWTP
RTGIAOCVEJ
VJKU VGUVTGURQPUG
_
_
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:
KPRWVGSWCNU 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:
OCTMGTUCTTC[
PGY4GIGZR/CTMGT
RK
PGY/CVEJ/CTMGT
RKúè
PGY/CTM.QIKE/CTMGT
KPRWVGSWCNURKúè
HQTGCEJ
OCTMGTUCUOCTMGT]
RTKPVIGVAENCUU
OCTMGT P
SWGUVKQPPGY6GZV3WGUVKQP
+NGDQMÎYOCRKúEKQDQM!OCTMGT
HQTGCEJ
CTTC[
RKúèE\VGT[CUTGURQPUG]
RTKPV VQFRQYKGFļTGURQPUG
KH
SWGUVKQP OCTM
TGURQPUG]
RTKPVY[ħOKGPKVCQFRQYKGFļ P
_GNUG]
RTKPVRQO[đMC P
_
_
_
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[ħOKGPKVCQFRQYKGFļ
QFRQYKGFļE\VGT[RQO[đMC
/CVEJ/CTMGT
QFRQYKGFļRKúèY[ħOKGPKVCQFRQYKGFļ
QFRQYKGFļE\VGT[RQO[đMC
/CTM.QIKE/CTMGT
QFRQYKGFļRKúèY[ħOKGPKVCQFRQYKGFļ
QFRQYKGFļE\VGT[Y[ħOKGPKVCQFRQYKGFļ
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
RTKXCVGUVCVWUCTTC[
HWPEVKQPJCPFNG.QIKP
WUGTRCUUKR]
UYKVEJ
TCPF
]
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A# 55WUGTKR
TGVVTWGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55WUGTKR
TGVHCNUGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A75 4A70-0190WUGTKR
TGVHCNUGDTGCM
_
TGVWTPTGV
_
RTKXCVGHWPEVKQPUGV5VCVWU
UVCVWUWUGTKR]
VJKU UVCVWUCTTC[
UVCVWUWUGTKR
_
HWPEVKQPIGV5VCVWU
]
TGVWTPVJKU 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:
HWPEVKQPJCPFNG.QIKP
WUGTRCUUKR]
UYKVEJ
TCPF
]
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A# 55WUGTKR
TGVVTWGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55WUGTKR
TGVHCNUGDTGCM
ECUG
226
Część III ♦ Wzorce
VJKU UGV5VCVWU
UGNH.1)+0A75 4A70-0190WUGTKR
TGVHCNUGDTGCM
_
.QIIGTNQI+2
WUGTKRVJKU IGV5VCVWU
TGVWTPTGV
_
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
WUGTKRVJKU 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):
KPVGTHCEG1DUGTXCDNG]
HWPEVKQPCVVCEJ
1DUGTXGTQDUGTXGT
HWPEVKQPFGVCEJ
1DUGTXGTQDUGTXGT
HWPEVKQPPQVKH[
_
Rozdział 11. ♦ Reprezentacja i realizacja zadań
227
Klasa Login…
RTKXCVGQDUGTXGTU
…
HWPEVKQPCVVCEJ
1DUGTXGTQDUGTXGT]
VJKU QDUGTXGTU=?QDUGTXGT
_
HWPEVKQPFGVCEJ
1DUGTXGTQDUGTXGT]
VJKU QDUGTXGTUCTTC[AFKHH
VJKU QDUGTXGTUCTTC[
QDUGTXGT
_
HWPEVKQPPQVKH[
]
HQTGCEJ
VJKU QDUGTXGTUCUQDU]
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
:
HWPEVKQPJCPFNG.QIKP
WUGTRCUUKR]
UYKVEJ
TCPF
]
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A# 55WUGTKR
TGVVTWGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55WUGTKR
TGVHCNUGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A75 4A70-0190WUGTKR
TGVHCNUGDTGCM
_
VJKU PQVKH[
TGVWTPTGV
_
Zdefiniujmy interfejs klas-obserwatorów:
KPVGTHCEG1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG
_
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:
ENCUU5GEWTKV[/QPKVQTGZVGPFU1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG]
UVCVWUQDUGTXCDNG IGV5VCVWU
228
Część III ♦ Wzorce
KH
UVCVWU=?.QIKP.1)+0A9410)A2#55]
wyślij wiadomość do administratora…
RTKPVAA .#55AA VY[U[đCOYKCFQOQħEKGOCKNFQCFOKPKUVTCVQTC P
_
_
_
ENCUU)GPGTCN.QIIGTGZVGPFU1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG]
UVCVWUQDUGTXCDNG IGV5VCVWU
dodaj dane sesji logowania do rejestru…
RTKPVAA .#55AA VFQFCLúYRKUFQTGLGUVTWNQIQYCPKC P
_
_
ENCUU2CTVPGTUJKR6QQNGZVGPFU1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG]
UVCVWUQDUGTXCDNG IGV5VCVWU
sprawdź adres IP…
jeśli adres rozpoznany, ustaw plik cookie…
RTKPVAA .#55AA VWUVCYKCORNKMEQQMKGFNCTQ\RQ\PCPGIQCFTGUW+2 P
_
_
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:
NQIKPPGY.QIKP
NQIKP CVVCEJ
PGY5GEWTKV[/QPKVQT
NQIKP CVVCEJ
PGY)GPGTCN.QIIGT
NQIKP CVVCEJ
PGY2CTVPGTUJKR6QQN
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:
KPVGTHCEG1DUGTXCDNG]
HWPEVKQPCVVCEJ
1DUGTXGTQDUGTXGT
HWPEVKQPFGVCEJ
1DUGTXGTQDUGTXGT
HWPEVKQPPQVKH[
_
ENCUU.QIKPKORNGOGPVU1DUGTXCDNG]
RTKXCVGQDUGTXGTUCTTC[
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
RTKXCVGUVCVWUCTTC[
HWPEVKQPCVVCEJ
1DUGTXGTQDUGTXGT]
VJKU QDUGTXGTU=?QDUGTXGT
_
HWPEVKQPFGVCEJ
1DUGTXGTQDUGTXGT]
VJKU QDUGTXGTUCTTC[AFKHH
VJKU QDUGTXGTUCTTC[
QDUGTXGT
_
HWPEVKQPPQVKH[
]
HQTGCEJ
VJKU QDUGTXGTUCUQDU]
QDU WRFCVG
VJKU
_
_
HWPEVKQPJCPFNG.QIKP
WUGTRCUUKR]
UYKVEJ
TCPF
]
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A# 55WUGTKR
TGVVTWGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A9410)A2#55WUGTKR
TGVHCNUGDTGCM
ECUG
VJKU UGV5VCVWU
UGNH.1)+0A75 4A70-0190WUGTKR
TGVHCNUGDTGCM
_
VJKU PQVKH[
TGVWTPTGV
_
230
Część III ♦ Wzorce
RTKXCVGHWPEVKQPUGV5VCVWU
UVCVWUWUGTKR]
VJKU UVCVWUCTTC[
UVCVWUWUGTKR
_
HWPEVKQPIGV5VCVWU
]
TGVWTPVJKU UVCVWU
_
_
KPVGTHCEG1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG
_
ENCUU5GEWTKV[/QPKVQTGZVGPFU1DUGTXGT]
HWPEVKQPWRFCVG
1DUGTXCDNGQDUGTXCDNG]
UVCVWUQDUGTXCDNG IGV5VCVWU
KH
UVCVWU=?.QIKP.1)+0A9410)A2#55]
wyślij wiadomość do administratora…
RTKPVAA .#55AA VY[U[đCOYKCFQOQħE
Pobierz darmowy fragment (pdf)