Ruby. Wzorce projektowe
Autor: Russ Olsen
Tłumaczenie: Mikołaj Szczepaniak
ISBN: 978-83-246-1688-6
Tytuł oryginału: Design Patterns in Ruby
(Addison-Wesley Professional Ruby Series)
Format: 172x245, stron: 370
Zwiększ elastycznoSć swojego kodu dzięki wzorcom projektowym!
" Jak rozpocząć przygodę z językiem Ruby?
" Jak wykorzystać drzemiące w nim możliwoSci?
" Jak zwiększyć elastycznoSć tworzonego kodu za pomocą wzorców projektowych?
Stworzony w 1995 roku przez Yukihiro Matsumoto język Ruby dzięki swym unikalnym
możliwoSciom zdobywa serca programistów na całym Swiecie. Cechy, które podbijają
to nieufne Srodowisko, to między innymi prosta składnia z wbudowanymi w nią
wyrażeniami regularnymi, automatyczne oczyszczanie pamięci i wiele, wiele innych.
Ogromna i chętna do pomocy społecznoSć czyni to rozwiązanie jeszcze bardziej
atrakcyjnym. Ruby pozwala na korzystanie ze wzorców projektowych zbioru zasad
i reguł prowadzących do celu w najlepszy, najszybszy i najbardziej elastyczny sposób.
Wzorce projektowe kojarzą się głównie z językami Java oraz C i C++. Książka Ruby.
Wzorce projektowe pokazuje, że można ich z powodzeniem używać również w języku
Ruby. Dowiesz się z niej, w jaki sposób wykorzystać znane wzorce, takie jak Observer,
Singleton czy też Proxy. Autor przedstawi Ci również nowe wzorce, które ze względu
na cechy języka Ruby mogą zostać w nim zastosowane. Jednak zanim przejdziesz
do ich omawiania, Russ poprowadzi Cię przez podstawy programowania w tym języku.
Nauczysz się używać między innymi pętli, instrukcji warunkowych, wyrażeń regularnych.
Niewątpliwie Twoją ciekawoSć wzbudzi tak zwany duck typing , który oczywiScie także
został dokładnie tu omówiony. Russ Olsen dzięki swojemu wieloletniemu doSwiadczeniu
każdy wzorzec ilustruje przykładem z życia wziętym. Ułatwi Ci to przyswojenie
i zastosowanie we własnych projektach przedstawionych tu wzorców.
" Podstawy programowania w języku Ruby
" Zastosowanie wzorców takich jak Observer, Composite, Iterator, Command
i wiele innych
" Wykorzystanie technik metaprogramowania do tworzenia obiektów
Wydawnictwo Helion
niestandardowych
ul. KoSciuszki 1c
" Wykorzystanie wyrażeń regularnych
44-100 Gliwice
" Użycie języków dziedzinowych
tel. 032 230 98 63
" Sposób instalacji języka Ruby
e-mail: helion@helion.pl
Korzystaj z doSwiadczenia najlepszych programistów używaj
wzorców projektowych w języku Ruby!
SPIS TRE CI
S owo wst pne .................................................................................................. 15
Przedmowa ........................................................................................................ 19
Podzi kowania .................................................................................................. 25
O autorze ............................................................................................................ 27
CZ I WZORCE PROJEKTOWE I RUBY .................................................29
Rozdzia 1. Budowa lepszych programów z wykorzystaniem
wzorców projektowych ................................................................................... 31
Banda Czworga ................................................................................................. 32
Wzorce dla wzorców ........................................................................................ 33
Oddzielaj elementy zmienne od elementów sta ych ...................... 33
Programuj pod k tem interfejsu, nie implementacji ....................... 34
Stosuj kompozycj zamiast dziedziczenia ........................................ 36
Deleguj, deleguj i jeszcze raz deleguj ................................................ 40
Czy dane rozwi zanie rzeczywi cie jest niezb dne ........................ 41
Czterna cie z dwudziestu trzech .................................................................... 43
Wzorce projektowe w j zyku Ruby? ............................................................. 45
Rozdzia 2. Pierwsze kroki w j zyku Ruby ...................................................................... 47
Interaktywny j zyk Ruby ................................................................................ 48
Przywitaj si ze wiatem .................................................................................. 48
Zmienne .............................................................................................................. 51
Typy Fixnum i Bignum .................................................................................... 52
Liczby zmiennoprzecinkowe .......................................................................... 53
W j zyku Ruby nie ma typów prostych ........................................................ 54
Kiedy brakuje obiektów& ............................................................................... 55
Prawda, fa sz i nil .............................................................................................. 55
Decyzje, decyzje ................................................................................................ 57
P tle ..................................................................................................................... 58
8 RUBY. WZORCE PROJEKTOWE
Wi cej o a cuchach .......................................................................................... 60
Symbole ............................................................................................................... 63
Tablice ................................................................................................................. 63
Tablice mieszaj ce ............................................................................................. 65
Wyra enia regularne ........................................................................................ 65
Nasza pierwsza klasa ........................................................................................ 66
Operacje na zmiennych egzemplarzy ........................................................... 68
Obiekt pyta: Kim jestem? ................................................................................. 70
Dziedziczenie, podklasy i nadklasy ............................................................... 71
Opcje argumentów ........................................................................................... 72
Modu y ................................................................................................................ 73
Wyj tki ................................................................................................................ 76
W tki ................................................................................................................... 77
Zarz dzanie odr bnymi plikami z kodem ród owym .............................. 78
Podsumowanie .................................................................................................. 79
CZ II WZORCE PROJEKTOWE W J ZYKU RUBY ..................................81
Rozdzia 3. Urozmaicanie algorytmów
za pomoc wzorca projektowego Template Method ................................. 83
Jak stawi czo o typowym problemom .......................................................... 84
Izolowanie elementów zachowuj cych dotychczasow form ................ 85
Odkrywanie wzorca projektowego Template Method .............................. 88
Metody zaczepienia .......................................................................................... 89
Gdzie si w a ciwie podzia y wszystkie te deklaracje? ............................... 92
Typy, bezpiecze stwo i elastyczno ............................................................. 93
Testy jednostkowe nie maj charakteru opcjonalnego ............................... 95
U ywanie i nadu ywanie wzorca projektowego Template Method ....... 97
Szablony w praktycznych zastosowaniach ................................................... 98
Podsumowanie .................................................................................................. 99
Rozdzia 4. Zast powanie algorytmu strategi .............................................................. 101
Deleguj, deleguj i jeszcze raz deleguj .......................................................... 102
Wspó dzielenie danych przez kontekst i strategi .................................... 104
Jeszcze raz o kaczym typowaniu .................................................................. 106
Obiekty Proc i bloki kodu .............................................................................. 107
Krótka analiza kilku prostych strategii ........................................................ 111
U ywanie i nadu ywanie wzorca projektowego Strategy ....................... 112
Wzorzec Strategy w praktycznych zastosowaniach .................................. 113
Podsumowanie ................................................................................................ 114
Rozdzia 5. Jak by na bie co dzi ki wzorcowi Observer ......................................... 117
Trzymamy r k na pulsie .............................................................................. 117
Jak skuteczniej trzyma r k na pulsie? ...................................................... 119
Wyodr bnianie mechanizmu umo liwiaj cego obserwacj .................... 122
Stosowanie bloków kodu w roli obserwatorów ......................................... 125
Odmiany wzorca projektowego Observer .............................................. 126
SPIS TRE CI 9
9
U ywanie i nadu ywanie wzorca projektowego Observer ..................... 127
Wzorzec Observer w praktycznych zastosowaniach ................................ 129
Podsumowanie ................................................................................................ 130
Rozdzia 6. Budowa wi kszej ca o ci z cz ci za pomoc wzorca Composite ......... 133
Ca o i cz ci ................................................................................................... 134
Tworzenie kompozytów ................................................................................ 136
Doskonalenie implementacji wzorca Composite
z wykorzystaniem operatorów .................................................................. 140
A mo e tablica w roli kompozytu? ............................................................... 141
K opotliwe ró nice .......................................................................................... 141
Wska niki w obie strony ................................................................................ 142
U ywanie i nadu ywanie wzorca projektowego Composite .................. 143
Kompozyty w praktycznych zastosowaniach ............................................ 145
Podsumowanie ................................................................................................ 147
Rozdzia 7. Przeszukiwanie kolekcji z wykorzystaniem wzorca Iterator ................ 149
Iteratory zewn trzne ...................................................................................... 149
Iteratory wewn trzne ..................................................................................... 152
Iteratory wewn trzne kontra iteratory wewn trzne ................................ 153
Niezrównany modu Enumerable ................................................................ 154
U ywanie i nadu ywanie wzorca projektowego Iterator ........................ 156
Iteratory w praktycznych zastosowaniach ................................................. 158
Podsumowanie ................................................................................................ 161
Rozdzia 8. Doprowadzanie spraw do ko ca za pomoc wzorca Command ........... 163
Eksplozja podklas ............................................................................................ 164
Prostsze rozwi zanie ...................................................................................... 165
Stosowanie bloków kodu w roli polece ..................................................... 166
Rejestrowanie polece .................................................................................... 167
Wycofywanie operacji za pomoc wzorca Command .............................. 170
Kolejkowanie polece .................................................................................... 173
U ywanie i nadu ywanie wzorca projektowego Command .................. 174
Wzorzec projektowy Command w praktycznych zastosowaniach ........ 175
Migracje w ramach interfejsu ActiveRecord ................................... 175
Madeleine ............................................................................................. 176
Podsumowanie ................................................................................................ 179
Rozdzia 9. Wype nianie luk z wykorzystaniem wzorca Adapter ............................. 181
Adaptery programowe ................................................................................... 182
Minimalne niedoci gni cia ............................................................................ 184
Czy alternatyw mo e by adaptowanie istniej cych klas? ..................... 186
Modyfikowanie pojedynczych obiektów .................................................... 187
Adaptowa czy modyfikowa ? ..................................................................... 188
U ywanie i nadu ywanie wzorca projektowego Adapter ....................... 190
Adaptery w praktycznych zastosowaniach ................................................ 190
Podsumowanie ................................................................................................ 191
10 RUBY. WZORCE PROJEKTOWE
Rozdzia 10. Tworzenie zewn trznego reprezentanta naszego obiektu
z wykorzystaniem wzorca Proxy ................................................................. 193
Rozwi zaniem s po rednicy ........................................................................ 194
Po rednik ochrony .......................................................................................... 196
Po rednicy zdalni ............................................................................................ 197
Po rednicy wirtualni jako rodek rozleniwiaj cy ...................................... 198
Eliminacja najbardziej uci liwych
elementów implementacji po redników .................................................. 200
Metody i przekazywanie komunikatów ......................................... 201
Metoda method_missing ................................................................... 202
Wysy anie komunikatów ................................................................... 203
Bezbolesne implementowanie po redników ................................. 203
U ywanie i nadu ywanie po redników ...................................................... 206
Wzorzec Proxy w praktycznych zastosowaniach ...................................... 207
Podsumowanie ................................................................................................ 208
Rozdzia 11. Doskonalenie obiektów za pomoc wzorca Decorator ........................... 211
Dekoratory: lekarstwo na brzydki kod ........................................................ 212
Dekoracja formalna ......................................................................................... 217
Jak upro ci model delegacji zada ............................................................. 218
Dynamiczna alternatywa dla wzorca projektowego Decorator .............. 219
Opakowywanie metod ....................................................................... 219
Dekorowanie za pomoc modu ów ................................................. 220
U ywanie i nadu ywanie wzorca projektowego Decorator .................... 221
Dekoratory w praktycznych zastosowaniach ............................................. 222
Podsumowanie ................................................................................................ 223
Rozdzia 12. Jak zyska pewno , e to ten jedyny,
z wykorzystaniem wzorca Singleton .......................................................... 225
Jeden obiekt, dost p globalny ....................................................................... 225
Zmienne i metody klasowe ........................................................................... 226
Zmienne klasowe ................................................................................ 226
Metody klasowe .................................................................................. 227
Pierwsza próba opracowania singletonu w Ruby ..................................... 228
Zarz dzanie jedynym obiektem ....................................................... 229
Upewnianie si , e istnieje tylko jeden ........................................... 230
Modu Singleton .............................................................................................. 231
Singletony leniwe i chciwe ............................................................................ 232
Konstrukcje alternatywne wzgl dem klasycznego singletonu ............... 232
Zmienne globalne jako singletony ................................................... 232
Klasy jako singletony .......................................................................... 233
Modu y jako singletony ..................................................................... 235
SPIS TRE CI 11
1
Pasy bezpiecze stwa kontra kaftan bezpiecze stwa ................................ 236
U ywanie i nadu ywanie wzorca projektowego Singleton .................... 237
Czy singletony nie s przypadkiem
zwyk ymi zmiennymi globalnymi? ............................................... 237
W a ciwie iloma singletonami dysponujemy? ............................... 238
Singletony i niezb dna wiedza ......................................................... 238
Eliminowanie utrudnie zwi zanych z testowaniem .................. 240
Singletony w praktycznych zastosowaniach .............................................. 241
Podsumowanie ................................................................................................ 242
Rozdzia 13. Wybór w a ciwej klasy za pomoc wzorca Factory ................................. 243
Inny rodzaj kaczego typowania .................................................................... 244
Powrót wzorca projektowego Template Method ...................................... 246
Sparametryzowane metody wytwórcze ...................................................... 248
Klasy to po prostu obiekty ............................................................................. 251
Z e wie ci: nasz program podbi wiat ........................................................ 252
Grupowe tworzenie obiektów ...................................................................... 253
Klasy to po prostu obiekty (raz jeszcze) ...................................................... 255
Korzystanie z nazw ......................................................................................... 257
U ywanie i nadu ywanie wzorców fabryk ................................................ 258
Wzorce fabryk w praktycznych zastosowaniach ....................................... 258
Podsumowanie ................................................................................................ 260
Rozdzia 14. Uproszczone konstruowanie obiektów
z wykorzystaniem wzorca Builder .............................................................. 263
Budowa komputerów ..................................................................................... 264
Klasy budowniczych polimorficznych ........................................................ 267
Klasy budowniczych mog te zapewni
bezpiecze stwo tworzenia obiektów ........................................................ 270
Klasy budowniczych wielokrotnego u ytku .............................................. 270
Lepsza implementacja budowniczych
z wykorzystaniem magicznych metod ..................................................... 271
U ywanie i nadu ywanie wzorca projektowego Builder ........................ 272
Klasy budowniczych w praktycznych zastosowaniach ............................ 273
Podsumowanie ................................................................................................ 274
Rozdzia 15. czenie systemu z wykorzystaniem interpretera ................................... 275
J zyk dostosowany do realizowanego zadania .......................................... 276
Konstruowanie interpretera .......................................................................... 277
Interpreter odnajdywania plików ................................................................ 279
Odnajdywanie wszystkich plików ................................................... 279
Wyszukiwanie plików wed ug nazw .............................................. 280
Wielkie pliki i pliki zapisywalne ....................................................... 281
Bardziej z o one operacje wyszukiwania z uwzgl dnieniem
logicznej negacji, koniunkcji i alternatywy ................................. 282
12 RUBY. WZORCE PROJEKTOWE
Tworzenie drzewa AST .................................................................................. 284
Prosty analizator sk adniowy ............................................................ 284
Interpreter bez analizatora sk adniowego? ..................................... 286
Analiza sk adniowa danych j zyka XML czy YAML? .................. 287
Generowanie z o onych analizatorów sk adniowych
za pomoc narz dzia Racc .............................................................. 288
A mo e wykorzysta analizator samego j zyka Ruby? ................ 288
U ywanie i nadu ywanie wzorca projektowego Interpreter .................. 289
Interpretery w praktycznych zastosowaniach ........................................... 290
Podsumowanie ................................................................................................ 291
CZ III WZORCE DLA J ZYKA RUBY ...................................................293
Rozdzia 16. Otwieranie systemów za pomoc j zyków dziedzinowych (DSL) ...... 295
J zyki dziedzinowe ......................................................................................... 296
J zyk DSL kopii zapasowej ............................................................................ 297
Czy to plik z danymi? Nie, to program! ...................................................... 297
Budowa j zyka PackRat ................................................................................. 299
czenie opracowanych dotychczas elementów w jedn ca o ............ 300
Krytyczne spojrzenie na j zyk PackRat ....................................................... 301
Doskonalenie j zyka PackRat ....................................................................... 302
U ywanie i nadu ywanie wewn trznych j zyków DSL ......................... 305
Wewn trzne j zyki DSL w praktycznych zastosowaniach ..................... 305
Podsumowanie ................................................................................................ 307
Rozdzia 17. Tworzenie niestandardowych obiektów
technik metaprogramowania ..................................................................... 309
Obiekty szyte na miar metoda po metodzie ............................................. 310
Obiekty niestandardowe tworzone modu po module ............................ 312
Wyczarowywanie zupe nie nowych metod ............................................... 313
Rzut okiem na wewn trzn struktur obiektu ........................................... 317
U ywanie i nadu ywanie metaprogramowania ........................................ 318
Metaprogramowanie w praktycznych zastosowaniach ........................... 319
Podsumowanie ................................................................................................ 322
Rozdzia 18. Konwencja ponad konfiguracj ................................................................... 323
Interfejs u ytkownika dobry dla... programistów ..................................... 325
Przewidywanie przysz ych potrzeb ................................................. 326
Oszcz d my u ytkownikom powtarzania swojej woli ................ 326
Udost pnianie szablonów ................................................................. 327
Bramka wiadomo ci ........................................................................................ 327
Wybór adaptera ............................................................................................... 329
adowanie klas ................................................................................................ 331
Dodanie prostych zabezpiecze ................................................................... 333
U atwianie u ytkownikowi wej cia w wiat
naszego oprogramowania ........................................................................... 335
SPIS TRE CI 13
1
Podsumowanie przyk adu bramki wiadomo ci ........................................ 336
U ywanie i nadu ywanie wzorca projektowego
Convention Over Configuration ............................................................... 337
Wzorzec Convention Over Configuration
w praktycznych zastosowaniach ............................................................... 338
Podsumowanie ................................................................................................ 339
Rozdzia 19. Konkluzja ......................................................................................................... 341
DODATKI ................................................................................345
Dodatek A Instalacja j zyka Ruby ................................................................................... 347
Instalacja Ruby w systemie Microsoft Windows ........................................ 347
Instalacja Ruby w systemie Linux i pozosta ych systemach
wywodz cych si z systemu UNIX ........................................................... 348
System Mac OS X ............................................................................................ 348
Dodatek B Pog biona analiza ......................................................................................... 349
Wzorce projektowe ......................................................................................... 349
Ruby .................................................................................................................. 350
Wyra enia regularne ...................................................................................... 352
Blogi i witryny internetowe ........................................................................... 352
Skorowidz ........................................................................................................ 353
ROZDZIA 4.
Zast powanie
algorytmu strategi
W poprzednim rozdziale szukali my odpowiedzi na pytanie: Jak zró nicowa wybran
cz algorytmu? Jak sprawi , by trzeci krok procesu pi ciokrokowego raz podejmowa
jedne dzia ania, a innym razem realizowa nieco inne zadania? W rozdziale 3. przyj li-
my rozwi zanie polegaj ce na stosowaniu wzorca projektowego Template Method,
czyli na tworzeniu klasy bazowej z metod szablonow odpowiedzialn za ogólne
przetwarzanie podklas charakterystycznych dla mechanizmów szczegó owych. Gdy-
by my raz chcieli realizowa jeden wariant, by innym razem stosowa mechanizm
alternatywny, powinni my opracowa dwie podklasy, po jednej dla obu scenariuszy.
Wzorzec projektowy Template Method ma, niestety, pewne wady, z których naj-
powa niejsz jest konieczno korzystania z relacji dziedziczenia (w a nie wokó niej
opracowano ten wzorzec). Jak wiemy z rozdzia u 1., stosowanie cis ej relacji dzie-
dziczenia niesie ze sob wiele negatywnych konsekwencji. Niezale nie od wysi ku,
jaki w o ymy w rozwa ne projektowanie naszego kodu, podklasy b d ci le zwi -
zane ze swoj nadklas , co w przypadku tej relacji jest zupe nie naturalne. Techniki
opracowane na podstawie relacji dziedziczenia, w tym wzorzec Template Method,
ograniczaj wi c elastyczno naszego kodu. Po wybraniu okre lonej wersji algo-
rytmu (w naszym przypadku takim krokiem by o utworzenie obiektu klasy HTML-
Report), zmiana tego trybu na inny mo e si okaza niezwykle trudna. Gdyby my
zastosowali wzorzec projektowy Template Method i zdecydowali si na zmian
formatu raportu, musieliby my utworzy nowy obiekt raportu, np. obiekt klasy
PlainTextReport, tylko po to, by u y nowego formatu. Mamy inne wyj cie?
102 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
DELEGUJ, DELEGUJ I JESZCZE RAZ DELEGUJ
Alternatywnym rozwi zaniem jest uwzgl dnienie rady sformu owanej przez Band
Czworga i przypomnian w rozdziale 1. tej ksi ki: wybierajmy technik delegowania
zada . Jaki b dzie efekt rezygnacji z ka dorazowego tworzenia podklas na rzecz
wyodr bnienia k opotliwego, zmienianego kodu do wyspecjalizowanej klasy? B dziemy
wówczas mogli opracowa ca rodzin klas, po jednej dla ka dej odmiany imple-
mentowanego mechanizmu. Poni ej przedstawiono przyk ad kodu odpowiedzialnego
za formatowanie raportów w j zyku HTML przeniesionego na poziom odr bnej klasy:
class Formatter
def output_report( title, text )
raise 'Wywo ano metod abstrakcyjn '
end
end
class HTMLFormatter < Formatter
def output_report( title, text )
puts('')
puts(' ')
puts("
#{title}")
puts(' ')
puts(' ')
text.each do |line|
puts("
#{line}
" )
end
puts(' ')
puts('')
end
end
Klas odpowiedzialn za formatowanie raportu w wersji tekstowej mo na by zaim-
plementowa w nast puj cy sposób:
class PlainTextFormatter < Formatter
def output_report(title, text)
puts("***** #{title} *****")
text.each do |line|
puts(line)
end
end
end
Uda o nam si przenie szczegó owy kod zwi zany z formatowaniem danych wyni-
kowych poza klas Report, zatem jej definicja b dzie teraz nieporównanie prostsza:
class Report
attr_reader :title, :text
attr_accessor :formatter
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 103
1
def initialize(formatter)
@title = 'Raport miesi czny'
@text = [ 'Wszystko idzie', 'naprawd dobrze.' ]
@formatter = formatter
end
def output_report
@formatter.output_report( @title, @text )
end
end
Okazuje si , e wprowadzona zmiana tylko nieznacznie komplikuje proces korzysta-
nia z klasy Report w nowym kszta cie. Musimy teraz przekazywa na wej ciu jej kon-
struktora w a ciwy obiekt formatuj cy:
report = Report.new(HTMLFormatter.new)
report.output_report
Banda Czworga okre li a technik wyodr bniania algorytmu do osobnego obiektu
mianem wzorca projektowego Strategy (patrz rysunek 4.1). Wzorzec Strategy opra-
cowano w my l za o enia, zgodnie z którym warto definiowa rodzin obiektów, tzw.
strategii, realizuj cych to samo zadanie w ró ny sposób (w naszym przypadku tym
zadaniem jest formatowanie raportu). Wszystkie obiekty strategii nie tylko realizuj to
samo zadanie, ale te obs uguj identyczny interfejs. W prezentowanym przyk adzie
ten wspólny interfejs ogranicza si do metody output_report. Skoro wszystkie obiekty
strategii z zewn trz wygl daj tak samo, u ytkownik strategii (nazywany przez Band
Czworga klas kontekstu ang. context class) mo e je traktowa jak wymienne
elementy. Oznacza to, e wybór strategii o tyle nie ma wielkiego znaczenia, e wszyst-
kie te obiekty wygl daj podobnie i realizuj t sam funkcj .
RYSUNEK 4.1.
Wzorzec projektowy
Strategy
Z drugiej strony wybór strategii ma znaczenie ze wzgl du na ró nice w sposobie reali-
zacji interesuj cych nas zada . W naszym przyk adzie jedna ze strategii formato-
wania generuje raport w j zyku HTML, druga generuje raport w formie zwyk ego
tekstu. Gdyby my zastosowali wzorzec Strategy w systemie obliczaj cym wysoko
podatku dochodowego, mogliby my u y jednej strategii do wyznaczania podatku
p aconego przez etatowego pracownika i innej do obliczania podatku uiszczanego
przez pracownika zatrudnionego na podstawie umowy o dzie o.
104 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
Wzorzec projektowy Strategy ma wiele praktycznych zalet. Przyk ad raportów po-
kazuje, e stosuj c ten wzorzec, mo emy zapewni skuteczniejsz izolacj naszego
kodu dzi ki wyodr bnieniu zbioru strategii poza klas g ówn . Wzorzec Strategy
zwalnia klas Report z jakiejkolwiek odpowiedzialno ci czy cho by konieczno ci
sk adowania informacji o formacie generowanych raportów.
Co wi cej, poniewa wzorzec Strategy opiera si na relacji kompozycji i technice de-
legacji (zamiast na dziedziczeniu), zmiana strategii w czasie wykonywania programu
nie stanowi adnego problemu. Wystarczy wymieni obiekt strategii:
report = Report.new(HTMLFormatter.new)
report.output_report
report.formatter = PlainTextFormatter.new
report.output_report
Wzorzec projektowy Strategy ma jedn cech wspóln ze wzorcem Template Method:
oba wzorce umo liwiaj nam koncentrowanie decyzji o wyborze sposobu realizacji
zlecanych zada w zaledwie jednym lub dwóch miejscach. W przypadku wzorca Tem-
plate Method w a ciw odmian algorytmu wybieramy, wskazuj c konkretn podklas ;
we wzorcu Strategy taki wybór sprowadza si do wskazania klasy strategii w czasie
wykonywania programu.
WSPÓ DZIELENIE DANYCH
PRZEZ KONTEKST I STRATEGI
Jedn z najwi kszych zalet wzorca projektowego Strategy jest izolowanie kodu kon-
tekstu i strategii w odr bnych klasach, co skutecznie dzieli dane pomi dzy dwa nie-
zale ne byty. Problem w tym, e musimy znale jaki sposób pokonania muru dziel -
cego oba byty, aby przekazywa informacje, którymi dysponuje kontekst i które s
niezb dne do prawid owego funkcjonowania strategii. Ogólnie mówi c, mamy do
wyboru dwa rozwi zania.
Po pierwsze, mo emy konsekwentnie stosowa dotychczasowe rozwi zanie polegaj ce
na przekazywaniu wszystkich danych niezb dnych do pracy obiektów strategii w for-
mie argumentów (przekazywanych przez obiekt kontekstu podczas wywo ywania me-
tod obiektów strategii). Warto pami ta , e w naszym przyk adzie systemu raportuj -
cego obiekt raportu by przekazywany do obiektów formatuj cych za po rednictwem
argumentów wywo a metody output_report. Przekazywanie kompletnych danych
ma t zalet , e pozwala skutecznie izolowa kontekst od obiektów strategii. Strategie
maj wspólny interfejs; kontekst korzysta tylko z tego interfejsu. Wady opisanej meto-
dy s widoczne w sytuacji, gdy musimy przekazywa mnóstwo z o onych danych,
co do których nie mamy adnych gwarancji, e rzeczywi cie zostan wykorzystane.
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 105
1
Po drugie, mo emy przekazywa dane z kontekstu do strategii w formie referencji do
samego obiektu kontekstu. Obiekt strategii mo e wówczas uzyskiwa niezb dne dane
za po rednictwem metod obiektu kontekstu. W naszym przyk adzie systemu rapor-
tuj cego odpowiedni model móg by mie nast puj c posta :
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(formatter)
@title = 'Raport miesi czny'
@text = [ 'Wszystko idzie', 'naprawd dobrze.' ]
@formatter = formatter
end
def output_report
@formatter.output_report(self)
end
end
Obiekt klasy Report przekazuje strategii formatowania referencj do samego siebie;
klasa formatuj ca mo e nast pnie uzyskiwa niezb dne dane za po rednictwem no-
wych metod title i text. Poni ej przedstawiono przebudowan klas HTMLFormatter
(przystosowan do korzystania z referencji do obiektu klasy Report):
class Formatter
def output_report(context)
raise 'Wywo ano metod abstrakcyjn '
end
end
class HTMLFormatter < Formatter
def output_report(context)
puts('')
puts(' ')
puts("
#{context.title}")
puts(' ')
puts(' ')
context.text.each do |line|
puts("
#{line}
")
end
puts(' ')
puts('')
end
end
Chocia opisana technika przekazywania kontekstu do strategii skutecznie uprasz-
cza przep yw danych, warto mie na uwadze to, e stosuj c wskazane rozwi zanie,
zacie niamy zwi zki cz ce kontekst i strategi . W ten sposób istotnie zwi kszamy
ryzyko wzajemnego uzale nienia klasy kontekstu i klas strategii.
106 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
JESZCZE RAZ O KACZYM TYPOWANIU
Przyk adow aplikacj generuj c raporty, któr pos ugiwali my si w tym rozdziale,
zbudowano zgodnie z zaleceniami Bandy Czworga odno nie do wzorca projektowego
Strategy. Nasza rodzina strategii formatowania sk ada si z abstrakcyjnej klasy ba-
zowej Formatter oraz dwóch podklas: HTMLFormatter i PlainTextFormatter. Pre-
zentowany model nie najlepiej pasuje do j zyka Ruby, poniewa klasa Formatter
w praktyce nie realizuje adnych dzia a istnieje tylko po to, by definiowa wspólny
interfejs wszystkich klas formatuj cych. Wspomniany problem w aden sposób nie
wp ywa na formaln poprawno naszego kodu tak napisany program po prostu
dzia a. Z drugiej strony takie rozwi zanie jest sprzeczne z przyj t w j zyku Ruby
filozofi tzw. kaczego typowania. Skoro klasy HTMLFormatter i PlainTextFormatter
implementuj wspólny interfejs przez zgodne definiowanie metody output_report,
wprowadzanie sztucznego tworu (w a nie w formie klasy pozbawionej dzia a ) po-
twierdzaj cego ten fakt nie ma wi kszego sensu.
Mo emy wyeliminowa z naszego projektu klas bazow Formatter za pomoc
zaledwie kilku uderze w klawisz Delete. Ostatecznie nasz kod b dzie mia nast -
puj c posta :
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(formatter)
@title = 'Raport miesi czny'
@text = [ 'Wszystko idzie', 'naprawd dobrze.' ]
@formatter = formatter
end
def output_report()
@formatter.output_report(self)
end
end
class HTMLFormatter
def output_report(context)
puts('')
puts(' ')
# Wy wietla pozosta e dane tego obiektu&
puts("
#{context.title}")
puts(' ')
puts(' ')
context.text.each do |line|
puts("
#{line}
")
end
puts(' ')
puts('')
end
end
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 107
1
class PlainTextFormatter
def output_report(context)
puts("***** #{context.title} *****")
context.text.each do |line|
puts(line)
end
end
end
Je li porównamy ten kod z poprzedni wersj , przekonamy si , e rezygnacja z klasy
bazowej Formatter nie wymaga a zbyt wielu dodatkowych zmian. Dzi ki dynamicznej
kontroli typów nadal mo emy generowa prawid owe raporty. Chocia obie wersje
dzia aj zgodnie z za o eniami, do wiata Ruby du o lepiej pasuje model pozbawiony
klasy bazowej Formatter.
OBIEKTY PROC I BLOKI KODU
Okazuje si , e eliminacja klasy bazowej nie jest jedynym sposobem dostosowania
wzorca projektowego Strategy do charakteru j zyka programowania Ruby. Zanim
jednak zrobimy kolejny krok, musimy wyja ni jeden z najciekawszych aspektów j -
zyka Ruby: bloki kodu i obiekty Proc.
Jako u ytkownicy obiektowych j zyków programowania sp dzamy mnóstwo czasu
na my leniu o obiektach i sposobach ich skutecznego czenia. Warto jednak zwróci
uwag na pewn asymetri wyst puj c w typowym postrzeganiu obiektów. Z regu y
nie mamy problemu z wyodr bnianiem danych poza obiekt mo emy na przyk ad
uzyska warto zmiennej @text obiektu raportu i przekazywa j dalej niezale nie
od pozosta ych sk adowych tego obiektu. Z drugiej strony zazwyczaj przyjmujemy,
e nasz kod jest ci le i nierozerwalnie zwi zany z poszczególnymi obiektami. Takie
przekonanie oczywi cie nie znajduje potwierdzenia w praktyce. Co w takim razie
powinni my zrobi , aby wyodr bni fragmenty kodu poza nasz obiekt i przekazywa
je dalej tak jak zwyk e obiekty? Okazuje si , e j zyk Ruby oferuje z my l o podob-
nych operacjach gotowe mechanizmy.
W j zyku Ruby Proc jest obiektem reprezentuj cym fragment kodu. Najpopularniej-
szym sposobem konstruowania obiektu Proc jest stosowanie metody lambda:
hello = lambda do
puts('Witaj')
puts('Jestem wewn trz obiektu Proc.')
end
W j zyku Ruby fragment kodu zawarty pomi dzy s owem kluczowym do a s owem
end okre la si mianem bloku kodu1. Metoda lambda zwraca nowy obiekt Proc, czyli
1
Stosuje si te terminy domkni cia (ang. closure) oraz lambdy (st d nazwa naszej metody tworz cej
obiekt Proc).
108 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
kontener obejmuj cy ca y kod zdefiniowany pomi dzy s owami do i end. W przed-
stawionym przyk adzie obiekt Proc jest wskazywany przez zmienn hello. Kod
reprezentowany przez obiekt Proc mo emy wykona , wywo uj c metod call (trudno
sobie wyobrazi lepsz nazw ). Je li w przedstawionym przyk adzie wywo amy metod
call obiektu Proc:
hello.call
otrzymamy komunikaty:
Witaj
Jestem wewn trz obiektu Proc.
Wyj tkowo cennym aspektem obiektów Proc jest zdolno do funkcjonowania w ota-
czaj cym je rodowisku. Oznacza to, e wszelkie zmienne widoczne w momencie
tworzenia obiektu Proc pozostaj dla tego obiektu dost pne tak e w czasie wykony-
wania programu. Na przyk ad w poni szym fragmencie kodu istnieje tylko jedna zmien-
na name:
name = 'Jan'
proc = Proc.new do
name = 'Maria'
end
proc.call
puts(name)
Kiedy wykonamy ten kod, zmiennej name w pierwszej kolejno ci zostanie przypisany
a cuch "Jan", po czym (po wywo aniu obiektu Proc) warto tej zmiennej zostanie
zast piona przez a cuch "Maria".
Oznacza to, e ostatecznie Ruby wy wietli a cuch "Maria". Z my l o programistach,
którym konstrukcja do-end wydaje si zbyt rozbudowana, Ruby oferuje krótsz sk ad-
ni z o on tylko z nawiasów klamrowych. Poni ej przedstawiono przyk ad u ycia
tej sk adni do utworzenia naszego obiektu Proc:
hello = lambda {
puts('Witaj, jestem wewn trz obiektu Proc')
}
Wielu programistów j zyka Ruby przyj o konwencj , zgodnie z któr konstrukcj
do-end stosuje si do bloków wielowierszowych, a nawiasy klamrowe stosuje si do
bloków jednowierszowych2. W tej sytuacji najlepsza wersja prezentowanego przy-
k adu b dzie mia a nast puj c posta :
hello = lambda {puts('Witaj, jestem wewn trz obiektu Proc')}
2
Uczciwo nakazuje wspomnie o istotnej ró nicy dziel cej obie konstrukcje. W wyra eniach j zyka
Ruby nawiasy klamrowe maj wy szy priorytet od pary s ów kluczowych do i end. Krótko mówi c,
nawiasy klamrowe s ci lej zwi zane z wyra eniami. Specyfika nawiasów klamrowych jest wi-
doczna dopiero wtedy, gdy zrezygnujemy z opcjonalnych nawiasów okr g ych.
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 109
1
Obiekty Proc pod wieloma wzgl dami przypominaj metody. Podobnie jak metody,
obiekty Proc nie tylko reprezentuj fragmenty kodu, ale te mog zwraca warto ci.
Obiekt Proc zawsze zwraca ostatni warto wyznaczon w danym bloku aby
zwróci warto z poziomu takiego obiektu, wystarczy si upewni , e jest ona wy-
znaczana przez jego ostatnie wyra enie. Wszelkie warto ci zwracane przez obiekty
Proc s przekazywane do kodu wywo uj cego za po rednictwem metody call.
Oznacza to, e kod w postaci:
return_24 = lambda {24}
puts(return_24.call)
wy wietli warto :
24
Dla obiektów Proc mo na te definiowa parametry, cho sk adnia tego rodzaju defini-
cji jest do nietypowa. Zamiast otacza list parametrów tradycyjnymi nawiasami
okr g ymi, nale y je umieszcza pomi dzy dwoma symbolami |:
multiply = lambda {|x, y| x * y}
Kod w tej formie definiuje obiekt Proc otrzymuj cy dwa parametry, wyznaczaj cy ich
iloczyn i zwracaj cy otrzyman warto . Aby wywo a obiekt Proc z parametrami,
wystarczy je przekaza na wej ciu metody call:
n = multiply.call(20, 3)
puts(n)
n = multiply.call(10, 50)
puts(n)
Po wykonaniu tego kodu otrzymamy nast puj ce warto ci:
60
500
Mo liwo przekazywania bloków kodu jest na tyle przydatna, e twórcy Ruby zde-
cydowali si zdefiniowa z my l o tej technice specjaln , skrócon konstrukcj sk a-
dniow . Je li chcemy przekaza blok kodu na wej ciu metody, wystarczy go do czy
do jej wywo ania. Tak wywo ana metoda mo e nast pnie wykona ten blok kodu
za pomoc s owa kluczowego yield. Poni ej zdefiniowano przyk adow metod
wy wietlaj c komunikat, wykonuj c otrzymany blok kodu i wy wietlaj c kolejny
komunikat:
def run_it
puts("Przed wykonaniem yield")
yield
puts("Po wykonaniu yield")
end
A tak mo e wygl da wywo anie metody run_it. Warto pami ta , e w ten sposób
dopisujemy blok kodu na koniec wywo ania naszej metody:
110 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
run_it do
puts('Witaj')
puts('Przybywam do Ciebie z wn trza bloku kodu')
end
Kiedy doklejamy blok kodu do wywo ania metody (jak w powy szym przyk adzie),
wspomniany blok (który w rzeczywisto ci ma posta obiektu Proc) jest przekazy-
wany do tej metody w formie dodatkowego, niewidocznego parametru. S owo kluczo-
we yield powoduje wi c wykonanie tego parametru. W wyniku wykonania powy -
szego kodu na ekranie zostan wy wietlone nast puj ce komunikaty:
Przed wykonaniem yield
Witaj
Przybywam do Ciebie z wn trza bloku kodu
Po wykonaniu yield
Je li przekazany blok kodu sam otrzymuje jakie parametry, nale y je przekaza za
po rednictwem s owa kluczowego yield. Oznacza to, e poni szy kod:
def run_it_with_parameter
puts("Przed wykonaniem yield")
yield(24)
puts("Po wykonaniu yield")
end
run_it_with_parameter do |x|
puts('Witaj z wn trza bloku kodu')
puts("Parametr x ma warto #{x}")
end
wy wietli nast puj ce komunikaty:
Przed wykonaniem yield
Witaj z wn trza bloku kodu
Parametr x ma warto 24
Po wykonaniu yield
W niektórych przypadkach warto zdefiniowa wprost parametr reprezentuj cy blok
kodu w takim przypadku blok przekazany na wej ciu naszej metody ma posta ar-
gumentu przypominaj cego typowe parametry. W tym celu nale y umie ci specjalny
parametr na ko cu listy parametrów tej metody. Tak przekazany parametr (poprze-
dzony znakiem &) zostanie przypisany obiektowi Proc utworzonemu na podstawie
bloku kodu do czonego do wywo ania danej metody. Oznacza to, e odpowiednikiem
przedstawionej powy ej metody run_it_with_parameters b dzie nast puj ca
konstrukcja:
def run_it_with_parameter(&block)
puts("Przed wykonaniem yield")
block.call(24)
puts("Po wykonaniu yield")
end
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 111
1
Symbol & mo na z powodzeniem stosowa tak e w przeciwnym kierunku. Gdyby my
umie cili obiekt Proc w zmiennej i chcieli go przekaza na wej ciu metody oczeku-
j cej bloku kodu, mogliby my przekonwertowa ten obiekt do postaci wymaganego
bloku, poprzedzaj c odpowiedni parametr w a nie znakiem &:
my_proc = lambda {|x| puts("Parametr x ma warto #{x}")}
run_it_with_parameter(&my_proc)
KRÓTKA ANALIZA
KILKU PROSTYCH STRATEGII
Co bloki kodu i obiekty Proc maj wspólnego ze wzorcem projektowym Strategy?
Najkrócej mówi c, strategi mo na postrzega jako blok wykonywalnego kodu,
który wie , jak zrealizowa okre lone zadanie (np. formatowanie tekstu) i który
opakowano w formie obiektu. Przytoczona definicja brzmi znajomo obiekt Proc
bywa okre lany w a nie jako fragment kodu opakowany w formie obiektu.
Wró my teraz do naszego przyk adowego systemu formatuj cego raporty, gdzie za-
stosowanie strategii w formie obiektu Proc okazuje si wyj tkowo proste. Zmiany,
które musimy wprowadzi w kodzie klasy Report, ograniczaj si do poprzedzenia
parametru przekazywanego na wej ciu metody initialize symbolem & i zmiany
nazwy wywo ywanej metody z output_report na call:
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(&formatter)
@title = 'Raport miesi czny'
@text = [ 'Wszystko idzie', 'naprawd dobrze.' ]
@formatter = formatter
end
def output_report
@formatter.call( self )
end
end
Z nieco inn sytuacj mamy jednak do czynienia w przypadku klas odpowiedzial-
nych za w a ciwe formatowanie. Musimy teraz stworzy obiekty Proc zamiast eg-
zemplarzy naszych wyspecjalizowanych klas formatuj cych:
HTML_FORMATTER = lambda do |context|
puts('')
puts(' ')
puts("
#{context.title}")
puts(' ')
puts(' ')
context.text.each do |line|
112 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
puts("
#{line}
" )
end
puts(' ')
puts
Skoro dysponujemy ju kodem formatuj cym w formie obiektu Proc, mo emy przy-
st pi do tworzenia raportów. Poniewa dysponujemy obiektem Proc, a konstruktor
klasy Report oczekuje bloku kodu, tworz c nowy obiekt tej klasy musimy poprze-
dzi wspomniany obiekt Proc znakiem &:
report = Report.new &HTML_FORMATTER
report.output_report
Po co w ogóle zajmujemy si problemem implementacji strategii w formie obiektu Proc?
Jednym z powodów jest brak konieczno ci definiowania specjalnych klas dla poszcze-
gólnych strategii wystarczy opakowa kod w ramach obiektu Proc. Co wi cej, sto-
suj c t technik mo emy tworzy strategie niemal z niczego, przekazuj c bloki kodu
na wej ciu istniej cej metody. Mo emy zaimplementowa na przyk ad mechanizm
formatuj cy raporty tekstowe w formie nast puj cego bloku kodu:
report = Report.new do |context|
puts("***** #{context.title} *****")
context.text.each do |line|
puts(line)
end
end
Programistom nieprzyzwyczajonym do tego rodzaju konstrukcji bloki kodu mog
si wydawa dziwaczne. Z drugiej strony powinni my pami ta , e proponowana
technika implementacji wzorca Strategy umo liwia zast pienie klas kontekstu, klas
bazow strategii i wiele konkretnych strategii (wraz ze wszystkimi niezb dnymi
obiektami) pojedyncz klas kontekstu i kilkoma blokami kodu.
Czy to oznacza, e powinni my raz na zawsze zapomnie o strategiach implementowa-
nych w postaci odr bnych klas? Nie do ko ca. Strategie w formie bloków kodu zdaj
egzamin tylko wtedy, gdy ich interfejs jest stosunkowo prosty i obejmuje zaledwie jedn
metod . Trudno si temu dziwi , skoro call jest jedyn metod , któr mo emy wy-
wo ywa dla obiektów Proc. Je li implementowane strategie wymagaj interfejsu
z o onego z wi kszej liczby metod, nie mamy wyboru musimy skorzysta z tra-
dycyjnych klas. Je li jednak interfejs strategii jest prosty, koniecznie powinni my
rozwa y u ycie bloków kodu.
U YWANIE I NADU YWANIE
WZORCA PROJEKTOWEGO STRATEGY
Najcz stsz przyczyn b dnego implementowania wzorca projektowego Strategy
jest niew a ciwe definiowanie interfejsu pomi dzy kontekstem a strategiami. Musimy
pami ta , e naszym celem jest wyodr bnienie kompletnego, spójnego i mniej lub
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 113
1
bardziej autonomicznego zadania poza obiekt kontekstu i delegowanie go do obiektu
strategii. Powinni my zwraca szczególn uwag zarówno na szczegó y interfejsu
cz cego kontekst ze strategi , jak i na zwi zki wyst puj ce pomi dzy obiema stro-
nami tej relacji. Stosowanie wzorca Strategy b dzie bezcelowe, je li zwi emy kontekst
z pierwsz strategi na tyle mocno, e uzupe nienie projektu o drug , trzeci i kolejne
strategie oka e si niemo liwe.
WZORZEC STRATEGY
W PRAKTYCZNYCH ZASTOSOWANIACH
Narz dzie rdoc (do czane do dystrybucji j zyka Ruby) zawiera wiele mechanizmów
opracowanych na podstawie klasycznego, zaproponowanego przez Band Czworga
i opartego na klasach wzorca projektowego Strategy. Zadaniem tego narz dzia jest
generowanie dokumentacji na podstawie kodu ród owego. rdoc oferuje mo liwo
dokumentowania zarówno programów napisanych w Ruby, jak i programów opra-
cowanych w C i (ratunku!) programów stworzonych w j zyku FORTRAN. Narz dzie
rdoc wykorzystuje wzorzec Strategy do obs ugi poszczególnych j zyków programo-
wania ka dy analizator sk adniowy (w a ciwy dla j zyków C, Ruby i FORTRAN)
ma posta strategii stworzonej z my l o innych danych wej ciowych.
Narz dzie rdoc oferuje te u ytkownikowi wybór formatu wyj ciowego mo emy
wybra jedn z wielu odmian j zyka HTML, j zyk XML b d jeden z formatów wyko-
rzystywanych przez polecenie ri j zyka Ruby. Jak nietrudno odgadn , ka dy z tych
formatów wyj ciowych tak e jest obs ugiwany przez wyspecjalizowan strategi .
Relacje cz ce poszczególne klasy strategii programu rdoc dobrze ilustruj ogólne
podej cie do problemu dziedziczenia stosowane w j zyku Ruby. Zwi zki klas repre-
zentuj cych poszczególne strategie przedstawiono na rysunku 4.2.
RYSUNEK 4.2.
Klasy generuj ce
narz dzia rdoc
Jak wida na rysunku 4.2, istniej cztery powi zane ze sob strategie formatowania
danych wyj ciowych (okre lanych w programie rdoc mianem generatorów) i jedna
strategia autonomiczna. Wszystkie cztery powi zane strategie generuj dokumentacj
w podobnym formacie znane wszystkim konstrukcje
otoczone nawiasami
114 Cz II " WZORCE PROJEKTOWE W J ZYKU RUBY
ostrymi 3. Ostatnia strategia generuje dane wyj ciowe na potrzeby polecenia
ri j zyka Ruby, które nie przypominaj ani kodu XML-a, ani kodu HTML-a. Jak
wynika z diagramu UML przedstawionego na rysunku 4.2, relacje cz ce poszczególne
klasy odzwierciedlaj szczegó y implementacyjne: klasy generuj ce dokumentacj
w formatach HTML, CHM i XML z natury rzeczy wspó dziel znaczn cz kodu,
st d decyzja twórców rdoc o zastosowaniu relacji dziedziczenia. Klasa RIGenerator
generuje zupe nie inne dane wynikowe (w formacie ca kowicie niezwi zanym z rodzin
j zyków XML i HTML). Twórcy rdoc nie zdecydowali si na wspó dzielenie jednej
nadklasy przez wszystkie klasy generatorów tylko dlatego, e wszystkie te klasy im-
plementuj ten sam interfejs. Ograniczyli si jedynie do zaimplementowania w a-
ciwych metod w opisanych klasach.
Okazuje si , e z dobrym przyk adem wykorzystania obiektu Proc w roli lekkiej strategii
mamy do czynienia na co dzie takie rozwi zanie zastosowano w przypadku tablic.
Je li chcemy posortowa zawarto tablicy j zyka Ruby, wywo ujemy metod sort:
a = ['ryszard', 'micha ', 'jan', 'daniel', 'robert']
a.sort
Metoda sort domy lnie sortuje obiekty sk adowane w tabeli, stosuj c naturalny
porz dek. Co w takim razie powinni my zrobi , je li chcemy u y innego schematu
porz dkowania elementów? Jak nale a oby na przyk ad posortowa a cuchy wed ug
d ugo ci? Wystarczy przekaza strategi porównywania obiektów w formie bloku
kodu:
a.sort { |a,b| a.length <=> b.length }
Metoda sort wywo uje nasz blok kodu za ka dym razem, gdy b dzie zmuszona po-
równa dwa elementy sortowanej tablicy. Nasz blok powinien zwraca warto 1, je li
pierwszy element jest wi kszy od drugiego; warto 0, je li oba elementy s równe,
i warto 1, je li wi kszy jest drugi element. Nieprzypadkowo dzia anie tego kodu
przypomina zachowanie operatora <=>.
PODSUMOWANIE
Wzorzec projektowy Strategy reprezentuje nieco inn , opart na delegowaniu zada
propozycj rozwi zywania tego samego problemu, który jest równie rozwi zywany
przez wzorzec Template Method. Zamiast upychania zmiennych cz ci algorytmu
w podklasach, implementujemy ka d z wersji tego algorytmu w odr bnym obiekcie.
Mo emy nast pnie urozmaica dzia ania tego algorytmu przez wskazywanie obiektowi
kontekstu ró nych obiektów strategii. Oznacza to, e o ile jedna strategia na przyk ad
generuje raport w formacie HTML, o tyle inna mo e generowa ten sam raport
3
Format CHM jest odmian HTML-a wykorzystywan do generowania plików pomocy firmy Microsoft.
Chcia bym te podkre li , e to kod narz dzia rdoc nie ja sugeruje, e XML jest odmian j -
zyka HTML.
Rozdzia 4. " ZAST POWANIE ALGORYTMU STRATEGI 115
1
w formacie PDF; podobnie, jedna strategia mo e wyznacza wysoko podatku od-
prowadzanego przez pracownika etatowego, by inna wylicza a podatek nale ny od
pracownika zatrudnionego na podstawie umowy o dzie o.
Mamy do dyspozycji kilka rozwi za dotycz cych przekazywania niezb dnych da-
nych pomi dzy obiektem kontekstu a obiektem strategii. Mo emy albo przekazywa
wszystkie dane w formie parametrów wywo ywanych metod obiektu strategii, albo
po prostu przekazywa obiektowi strategii referencj do ca ego obiektu kontekstu.
Bloki kodu j zyka Ruby, które w istocie maj posta kodu opakowywanego w ramach
tworzonego na bie co obiektu (a konkretnie obiektu Proc), wprost doskonale na-
daj si do b yskawicznego konstruowania prostych obiektów strategii.
Jak si nied ugo przekonamy, wzorzec projektowy Strategy przypomina (przynajm-
niej na pierwszy rzut oka) wiele innych wzorców. Wzorzec Strategy wymusza stoso-
wanie obiektu (nazywanego kontekstem), który odpowiada za realizacj okre lonego
zadania. Okazuje si jednak, e wykonanie tego zadania wymaga od kontekstu
skorzystania z pomocy innego obiektu (okre lanego mianem strategii). Z bardzo
podobnym modelem mamy do czynienia w przypadku wzorca projektowego Ob-
server (obserwatora), gdzie obiekt realizuj cy pewne zadania kieruje wywo ania do
drugiego obiektu, bez którego jego funkcjonowanie by oby niemo liwe.
Okazuje si , e jedyn ró nic dziel c oba te wzorce jest intencja programisty. Celem
wzorca projektowego Strategy jest dostarczenie obiektowi kontekstu innego obiektu,
który wie , jak wykona okre lon wersj algorytmu. Zupe nie inny cel przy wieca
programi cie stosuj cemu wzorzec Observer otó stosujemy go wtedy, gdy&
Chyba powinni my te rozwa ania przenie do innego rozdzia u (tak si sk ada, e
b dzie to kolejny rozdzia ).
Wyszukiwarka
Podobne podstrony:
informatyka ajax wzorce projektowe michael mahemoff ebookBYT Wzorce projektowe wyklady z 10 i 24 11 2006Architektura systemow zarzadzania przedsiebiorstwem Wzorce projektoweC Wzorce projektoweAjax Wzorce projektoweVisual Basic Wzorce projektoweAjax Wzorce projektowewięcej podobnych podstron