Ruby. Wzorce projektowe

23
Wydawnictwo Helion ul. Kociuszki 1c 44-100 Gliwice tel. 032 230 98 63 e-mail: [email protected] 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 elastyczno swojego kodu dziŒki wzorcom projektowym! Jak rozpocz„ przygodŒ z jŒzykiem Ruby? Jak wykorzysta drzemi„ce w nim mo¿liwoci? Jak zwiŒkszy elastyczno tworzonego kodu za pomoc„ wzorcw projektowych? Stworzony w 1995 roku przez Yukihiro Matsumoto jŒzyk Ruby dziŒki swym unikalnym mo¿liwociom zdobywa serca programistw na ca‡ym wiecie. Cechy, ktre podbijaj„ to nieufne rodowisko, 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‡eczno czyni to rozwi„zanie jeszcze bardziej atrakcyjnym. Ruby pozwala na korzystanie ze wzorcw projektowych zbioru zasad i regu‡ prowadz„cych do celu w najlepszy, najszybszy i najbardziej elastyczny sposb. 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 rwnie¿ w jŒzyku Ruby. Dowiesz siŒ z niej, w jaki sposb wykorzysta znane wzorce, takie jak Observer, Singleton czy te¿ Proxy. Autor przedstawi Ci rwnie¿ nowe wzorce, ktre 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„ ciekawo wzbudzi tak zwany duck typing, ktry oczywicie tak¿e zosta‡ dok‡adnie tu omwiony. Russ Olsen dziŒki swojemu wieloletniemu dowiadczeniu ka¿dy wzorzec ilustruje przyk‡adem z ¿ycia wziŒtym. U‡atwi Ci to przyswojenie i zastosowanie we w‡asnych projektach przedstawionych tu wzorcw. Podstawy programowania w jŒzyku Ruby Zastosowanie wzorcw takich jak Observer, Composite, Iterator, Command i wiele innych Wykorzystanie technik metaprogramowania do tworzenia obiektw niestandardowych Wykorzystanie wyra¿eæ regularnych U¿ycie jŒzykw dziedzinowych Sposb instalacji jŒzyka Ruby Korzystaj z dowiadczenia najlepszych programistw u¿ywaj wzorcw projektowych w jŒzyku Ruby!

description

Zwiększ elastyczność swojego kodu dzięki wzorcom projektowym! * Jak rozpocząć przygodę z językiem Ruby? * Jak wykorzystać drzemiące w nim możliwości? * Jak zwiększyć elastyczność tworzonego kodu za pomocą wzorców projektowych? Stworzony w 1995 roku przez Yukihiro Matsumoto język Ruby dzięki swym unikalnym możliwościom zdobywa serca programistów na całym świecie. Cechy, które podbijają to nieufne środowisko, 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łeczność 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ą ciekawość wzbudzi tak zwany „duck typing”, który oczywiście także został dokładnie tu omówiony. Russ Olsen dzięki swojemu wieloletniemu doświadczeniu 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 niestandardowych * Wykorzystanie wyrażeń regularnych * Użycie języków dziedzinowych * Sposób instalacji języka Ruby Korzystaj z doświadczenia najlepszych programistów - używaj wzorców projektowych w języku Ruby!

Transcript of Ruby. Wzorce projektowe

Page 1: Ruby. Wzorce projektowe

Wydawnictwo Helionul. Ko�ciuszki 1c44-100 Gliwicetel. 032 230 98 63e-mail: [email protected]

Ruby. Wzorce projektoweAutor: Russ OlsenT³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 elastyczno�æ swojego kodu dziêki wzorcom projektowym!

� Jak rozpocz¹æ przygodê z jêzykiem Ruby? � Jak wykorzystaæ drzemi¹ce w nim mo¿liwo�ci? � Jak zwiêkszyæ elastyczno�æ tworzonego kodu za pomoc¹ wzorców projektowych?

Stworzony w 1995 roku przez Yukihiro Matsumoto jêzyk Ruby dziêki swym unikalnym mo¿liwo�ciom zdobywa serca programistów na ca³ym �wiecie. Cechy, które podbijaj¹to nieufne �rodowisko, 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³eczno�æ czyni to rozwi¹zanie jeszcze bardziej atrakcyjnym. Ruby pozwala na korzystanie ze wzorców projektowych � zbioru zasadi 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êduna cechy jêzyka Ruby mog¹ zostaæ w nim zastosowane. Jednak zanim przejdzieszdo 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¹ ciekawo�æ wzbudzi tak zwany �duck typing�, który oczywi�cie tak¿e zosta³ dok³adnie tu omówiony. Russ Olsen dziêki swojemu wieloletniemu do�wiadczeniu ka¿dy wzorzec ilustruje przyk³adem z ¿ycia wziêtym. U³atwi Ci to przyswojeniei 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 niestandardowych � Wykorzystanie wyra¿eñ regularnych � U¿ycie jêzyków dziedzinowych � Sposób instalacji jêzyka Ruby

Korzystaj z do�wiadczenia najlepszych programistów � u¿ywajwzorców projektowych w jêzyku Ruby!

Page 2: Ruby. Wzorce projektowe

SPIS TRE�CI

S�owo wst�pne .................................................................................................. 15 Przedmowa ........................................................................................................ 19 Podzi�kowania .................................................................................................. 25 O autorze ............................................................................................................ 27

CZ��� I WZORCE PROJEKTOWE I RUBY .................................................29Rozdzia� 1. Budowa lepszych programów z wykorzystaniem

wzorców projektowych ................................................................................... 31Banda Czworga ................................................................................................. 32Wzorce dla wzorców ........................................................................................ 33

Oddzielaj elementy zmienne od elementów sta�ych ...................... 33Programuj pod k�tem interfejsu, nie implementacji ....................... 34Stosuj kompozycj� zamiast dziedziczenia ........................................ 36Deleguj, deleguj i jeszcze raz deleguj ................................................ 40Czy dane rozwi�zanie rzeczywi�cie jest niezb�dne ........................ 41

Czterna�cie z dwudziestu trzech .................................................................... 43Wzorce projektowe w j�zyku Ruby? ............................................................. 45

Rozdzia� 2. Pierwsze kroki w j�zyku Ruby ...................................................................... 47Interaktywny j�zyk Ruby ................................................................................ 48Przywitaj si� ze �wiatem .................................................................................. 48Zmienne .............................................................................................................. 51Typy Fixnum i Bignum .................................................................................... 52Liczby zmiennoprzecinkowe .......................................................................... 53W j�zyku Ruby nie ma typów prostych ........................................................ 54Kiedy brakuje obiektów… ............................................................................... 55Prawda, fa�sz i nil .............................................................................................. 55Decyzje, decyzje ................................................................................................ 57P�tle ..................................................................................................................... 58

Page 3: Ruby. Wzorce projektowe

8 RUBY. WZORCE PROJEKTOWE

Wi�cej o �acuchach .......................................................................................... 60Symbole ............................................................................................................... 63Tablice ................................................................................................................. 63Tablice mieszaj�ce ............................................................................................. 65Wyra�enia regularne ........................................................................................ 65Nasza pierwsza klasa ........................................................................................ 66Operacje na zmiennych egzemplarzy ........................................................... 68Obiekt pyta: Kim jestem? ................................................................................. 70Dziedziczenie, podklasy i nadklasy ............................................................... 71Opcje argumentów ........................................................................................... 72Modu�y ................................................................................................................ 73Wyj�tki ................................................................................................................ 76W�tki ................................................................................................................... 77Zarz�dzanie odr�bnymi plikami z kodem �ród�owym .............................. 78Podsumowanie .................................................................................................. 79

CZ��� II WZORCE PROJEKTOWE W J�ZYKU RUBY ..................................81Rozdzia� 3. Urozmaicanie algorytmów

za pomoc� wzorca projektowego Template Method ................................. 83Jak stawi� czo�o typowym problemom .......................................................... 84Izolowanie elementów zachowuj�cych dotychczasow� form� ................ 85Odkrywanie wzorca projektowego Template Method .............................. 88Metody zaczepienia .......................................................................................... 89Gdzie si� w�a�ciwie podzia�y wszystkie te deklaracje? ............................... 92Typy, bezpieczestwo i elastyczno�� ............................................................. 93Testy jednostkowe nie maj� charakteru opcjonalnego ............................... 95U�ywanie i nadu�ywanie wzorca projektowego Template Method ....... 97Szablony w praktycznych zastosowaniach ................................................... 98Podsumowanie .................................................................................................. 99

Rozdzia� 4. Zast�powanie algorytmu strategi� .............................................................. 101Deleguj, deleguj i jeszcze raz deleguj .......................................................... 102Wspó�dzielenie danych przez kontekst i strategi� .................................... 104Jeszcze raz o kaczym typowaniu .................................................................. 106Obiekty Proc i bloki kodu .............................................................................. 107Krótka analiza kilku prostych strategii ........................................................ 111U�ywanie i nadu�ywanie wzorca projektowego Strategy ....................... 112Wzorzec Strategy w praktycznych zastosowaniach .................................. 113Podsumowanie ................................................................................................ 114

Rozdzia� 5. Jak by� na bie��co dzi�ki wzorcowi Observer ......................................... 117Trzymamy r�k� na pulsie .............................................................................. 117Jak skuteczniej trzyma� r�k� na pulsie? ...................................................... 119Wyodr�bnianie mechanizmu umo�liwiaj�cego obserwacj� .................... 122Stosowanie bloków kodu w roli obserwatorów ......................................... 125Odmiany wzorca projektowego Observer .............................................. 126

Page 4: Ruby. Wzorce projektowe

SPIS TRE�CI 99

U�ywanie i nadu�ywanie wzorca projektowego Observer ..................... 127Wzorzec Observer w praktycznych zastosowaniach ................................ 129Podsumowanie ................................................................................................ 130

Rozdzia� 6. Budowa wi�kszej ca�oci z cz�ci za pomoc� wzorca Composite ......... 133Ca�o�� i cz��ci ................................................................................................... 134Tworzenie kompozytów ................................................................................ 136Doskonalenie implementacji wzorca Composite

z wykorzystaniem operatorów .................................................................. 140A mo�e tablica w roli kompozytu? ............................................................... 141K�opotliwe ró�nice .......................................................................................... 141Wska�niki w obie strony ................................................................................ 142U�ywanie i nadu�ywanie wzorca projektowego Composite .................. 143Kompozyty w praktycznych zastosowaniach ............................................ 145Podsumowanie ................................................................................................ 147

Rozdzia� 7. Przeszukiwanie kolekcji z wykorzystaniem wzorca Iterator ................ 149Iteratory zewn�trzne ...................................................................................... 149Iteratory wewn�trzne ..................................................................................... 152Iteratory wewn�trzne kontra iteratory wewn�trzne ................................ 153Niezrównany modu� Enumerable ................................................................ 154U�ywanie i nadu�ywanie wzorca projektowego Iterator ........................ 156Iteratory w praktycznych zastosowaniach ................................................. 158Podsumowanie ................................................................................................ 161

Rozdzia� 8. Doprowadzanie spraw do koca za pomoc� wzorca Command ........... 163Eksplozja podklas ............................................................................................ 164Prostsze rozwi�zanie ...................................................................................... 165Stosowanie bloków kodu w roli polece ..................................................... 166Rejestrowanie polece .................................................................................... 167Wycofywanie operacji za pomoc� wzorca Command .............................. 170Kolejkowanie polece .................................................................................... 173U�ywanie i nadu�ywanie wzorca projektowego Command .................. 174Wzorzec projektowy Command w praktycznych zastosowaniach ........ 175

Migracje w ramach interfejsu ActiveRecord ................................... 175Madeleine ............................................................................................. 176

Podsumowanie ................................................................................................ 179

Rozdzia� 9. Wype�nianie luk z wykorzystaniem wzorca Adapter ............................. 181Adaptery programowe ................................................................................... 182Minimalne niedoci�gni�cia ............................................................................ 184Czy alternatyw� mo�e by� adaptowanie istniej�cych klas? ..................... 186Modyfikowanie pojedynczych obiektów .................................................... 187Adaptowa� czy modyfikowa�? ..................................................................... 188U�ywanie i nadu�ywanie wzorca projektowego Adapter ....................... 190Adaptery w praktycznych zastosowaniach ................................................ 190Podsumowanie ................................................................................................ 191

Page 5: Ruby. Wzorce projektowe

10 RUBY. WZORCE PROJEKTOWE

Rozdzia� 10. Tworzenie zewn�trznego reprezentanta naszego obiektuz wykorzystaniem wzorca Proxy ................................................................. 193Rozwi�zaniem s� po�rednicy ........................................................................ 194Po�rednik ochrony .......................................................................................... 196Po�rednicy zdalni ............................................................................................ 197Po�rednicy wirtualni jako �rodek rozleniwiaj�cy ...................................... 198Eliminacja najbardziej uci��liwych

elementów implementacji po�redników .................................................. 200Metody i przekazywanie komunikatów ......................................... 201Metoda method_missing ................................................................... 202Wysy�anie komunikatów ................................................................... 203Bezbolesne implementowanie po�redników ................................. 203

U�ywanie i nadu�ywanie po�redników ...................................................... 206Wzorzec Proxy w praktycznych zastosowaniach ...................................... 207Podsumowanie ................................................................................................ 208

Rozdzia� 11. Doskonalenie obiektów za pomoc� wzorca Decorator ........................... 211Dekoratory: lekarstwo na brzydki kod ........................................................ 212Dekoracja formalna ......................................................................................... 217Jak upro�ci� model delegacji zada ............................................................. 218Dynamiczna alternatywa dla wzorca projektowego Decorator .............. 219

Opakowywanie metod ....................................................................... 219Dekorowanie za pomoc� modu�ów ................................................. 220

U�ywanie i nadu�ywanie wzorca projektowego Decorator .................... 221Dekoratory w praktycznych zastosowaniach ............................................. 222Podsumowanie ................................................................................................ 223

Rozdzia� 12. Jak zyska� pewno�, �e to ten jedyny,z wykorzystaniem wzorca Singleton .......................................................... 225Jeden obiekt, dost�p globalny ....................................................................... 225Zmienne i metody klasowe ........................................................................... 226

Zmienne klasowe ................................................................................ 226Metody klasowe .................................................................................. 227

Pierwsza próba opracowania singletonu w Ruby ..................................... 228Zarz�dzanie jedynym obiektem ....................................................... 229Upewnianie si�, �e istnieje tylko jeden ........................................... 230

Modu� Singleton .............................................................................................. 231Singletony leniwe i chciwe ............................................................................ 232Konstrukcje alternatywne wzgl�dem klasycznego singletonu ............... 232

Zmienne globalne jako singletony ................................................... 232Klasy jako singletony .......................................................................... 233Modu�y jako singletony ..................................................................... 235

Page 6: Ruby. Wzorce projektowe

SPIS TRE�CI 111

Pasy bezpieczestwa kontra kaftan bezpieczestwa ................................ 236U�ywanie i nadu�ywanie wzorca projektowego Singleton .................... 237

Czy singletony nie s� przypadkiemzwyk�ymi zmiennymi globalnymi? ............................................... 237

W�a�ciwie iloma singletonami dysponujemy? ............................... 238Singletony i niezb�dna wiedza ......................................................... 238Eliminowanie utrudnie zwi�zanych z testowaniem .................. 240

Singletony w praktycznych zastosowaniach .............................................. 241Podsumowanie ................................................................................................ 242

Rozdzia� 13. Wybór w�aciwej klasy za pomoc� wzorca Factory ................................. 243Inny rodzaj kaczego typowania .................................................................... 244Powrót wzorca projektowego Template Method ...................................... 246Sparametryzowane metody wytwórcze ...................................................... 248Klasy to po prostu obiekty ............................................................................. 251Z�e wie�ci: nasz program podbi� �wiat ........................................................ 252Grupowe tworzenie obiektów ...................................................................... 253Klasy to po prostu obiekty (raz jeszcze) ...................................................... 255Korzystanie z nazw ......................................................................................... 257U�ywanie i nadu�ywanie wzorców fabryk ................................................ 258Wzorce fabryk w praktycznych zastosowaniach ....................................... 258Podsumowanie ................................................................................................ 260

Rozdzia� 14. Uproszczone konstruowanie obiektówz wykorzystaniem wzorca Builder .............................................................. 263Budowa komputerów ..................................................................................... 264Klasy budowniczych polimorficznych ........................................................ 267Klasy budowniczych mog� te� zapewni�

bezpieczestwo tworzenia obiektów ........................................................ 270Klasy budowniczych wielokrotnego u�ytku .............................................. 270Lepsza implementacja budowniczych

z wykorzystaniem magicznych metod ..................................................... 271U�ywanie i nadu�ywanie wzorca projektowego Builder ........................ 272Klasy budowniczych w praktycznych zastosowaniach ............................ 273Podsumowanie ................................................................................................ 274

Rozdzia� 15. ��czenie systemu z wykorzystaniem interpretera ................................... 275J�zyk dostosowany do realizowanego zadania .......................................... 276Konstruowanie interpretera .......................................................................... 277Interpreter odnajdywania plików ................................................................ 279

Odnajdywanie wszystkich plików ................................................... 279Wyszukiwanie plików wed�ug nazw .............................................. 280Wielkie pliki i pliki zapisywalne ....................................................... 281Bardziej z�o�one operacje wyszukiwania z uwzgl�dnieniem

logicznej negacji, koniunkcji i alternatywy ................................. 282

Page 7: Ruby. Wzorce projektowe

12 RUBY. WZORCE PROJEKTOWE

Tworzenie drzewa AST .................................................................................. 284Prosty analizator sk�adniowy ............................................................ 284Interpreter bez analizatora sk�adniowego? ..................................... 286Analiza sk�adniowa danych j�zyka XML czy YAML? .................. 287Generowanie z�o�onych analizatorów sk�adniowych

za pomoc� narz�dzia Racc .............................................................. 288A mo�e wykorzysta� analizator samego j�zyka Ruby? ................ 288

U�ywanie i nadu�ywanie wzorca projektowego Interpreter .................. 289Interpretery w praktycznych zastosowaniach ........................................... 290Podsumowanie ................................................................................................ 291

CZ��� III WZORCE DLA J�ZYKA RUBY ...................................................293Rozdzia� 16. Otwieranie systemów za pomoc� j�zyków dziedzinowych (DSL) ...... 295

J�zyki dziedzinowe ......................................................................................... 296J�zyk DSL kopii zapasowej ............................................................................ 297Czy to plik z danymi? Nie, to program! ...................................................... 297Budowa j�zyka PackRat ................................................................................. 299�czenie opracowanych dotychczas elementów w jedn� ca�o�� ............ 300Krytyczne spojrzenie na j�zyk PackRat ....................................................... 301Doskonalenie j�zyka PackRat ....................................................................... 302U�ywanie i nadu�ywanie wewn�trznych j�zyków DSL ......................... 305Wewn�trzne j�zyki DSL w praktycznych zastosowaniach ..................... 305Podsumowanie ................................................................................................ 307

Rozdzia� 17. Tworzenie niestandardowych obiektówtechnik� metaprogramowania ..................................................................... 309Obiekty szyte na miar� metoda po metodzie ............................................. 310Obiekty niestandardowe tworzone modu� po module ............................ 312Wyczarowywanie zupe�nie nowych metod ............................................... 313Rzut okiem na wewn�trzn� struktur� obiektu ........................................... 317U�ywanie i nadu�ywanie metaprogramowania ........................................ 318Metaprogramowanie w praktycznych zastosowaniach ........................... 319Podsumowanie ................................................................................................ 322

Rozdzia� 18. Konwencja ponad konfiguracj� ................................................................... 323Interfejs u�ytkownika dobry dla... programistów ..................................... 325

Przewidywanie przysz�ych potrzeb ................................................. 326Oszcz�d�my u�ytkownikom powtarzania swojej woli ................ 326Udost�pnianie szablonów ................................................................. 327

Bramka wiadomo�ci ........................................................................................ 327Wybór adaptera ............................................................................................... 329adowanie klas ................................................................................................ 331Dodanie prostych zabezpiecze ................................................................... 333U�atwianie u�ytkownikowi wej�cia w �wiat

naszego oprogramowania ........................................................................... 335

Page 8: Ruby. Wzorce projektowe

SPIS TRE�CI 113

Podsumowanie przyk�adu bramki wiadomo�ci ........................................ 336U�ywanie i nadu�ywanie wzorca projektowego

Convention Over Configuration ............................................................... 337Wzorzec Convention Over Configuration

w praktycznych zastosowaniach ............................................................... 338Podsumowanie ................................................................................................ 339

Rozdzia� 19. Konkluzja ......................................................................................................... 341

DODATKI ................................................................................345Dodatek A Instalacja j�zyka Ruby ................................................................................... 347

Instalacja Ruby w systemie Microsoft Windows ........................................ 347Instalacja Ruby w systemie Linux i pozosta�ych systemach

wywodz�cych si� z systemu UNIX ........................................................... 348System Mac OS X ............................................................................................ 348

Dodatek B Pog��biona analiza ......................................................................................... 349Wzorce projektowe ......................................................................................... 349Ruby .................................................................................................................. 350Wyra�enia regularne ...................................................................................... 352Blogi i witryny internetowe ........................................................................... 352

Skorowidz ........................................................................................................ 353

Page 9: Ruby. Wzorce projektowe

ROZDZIA� 4.

Zast�powaniealgorytmu 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ólneprzetwarzanie podklas charakterystycznych dla mechanizmów szczegó�owych. Gdy-by�my raz chcieli realizowa� jeden wariant, by innym razem stosowa� mechanizmalternatywny, 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ó� niejopracowano 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. Technikiopracowane 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�myzastosowali wzorzec projektowy Template Method i zdecydowali si� na zmian�formatu raportu, musieliby�my utworzy� nowy obiekt raportu, np. obiekt klasyPlainTextReport, tylko po to, by u�y� nowego formatu. Mamy inne wyj�cie?

Page 10: Ruby. Wzorce projektowe

102 Cz��� II • WZORCE PROJEKTOWE W J�ZYKU RUBY

DELEGUJ, DELEGUJ I JESZCZE RAZ DELEGUJAlternatywnym rozwi�zaniem jest uwzgl�dnienie rady sformu�owanej przez Band�Czworga i przypomnian� w rozdziale 1. tej ksi��ki: wybierajmy technik� delegowaniazada. Jaki b�dzie efekt rezygnacji z ka�dorazowego tworzenia podklas na rzeczwyodr�bnienia k�opotliwego, zmienianego kodu do wyspecjalizowanej klasy? B�dziemywówczas mogli opracowa� ca�� rodzin� klas, po jednej dla ka�dej odmiany imple-mentowanego mechanizmu. Poni�ej przedstawiono przyk�ad kodu odpowiedzialnegoza 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�' endend

class HTMLFormatter < Formatter def output_report( title, text ) puts('<html>') puts(' <head>') puts(" <title>#{title}</title>") puts(' </head>') puts(' <body>') text.each do |line| puts(" <p>#{line}</p>" ) end puts(' </body>') puts('</html>') endend

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 endend

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

Page 11: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1103

def initialize(formatter) @title = 'Raport miesi�czny' @text = [ 'Wszystko idzie', 'naprawd� dobrze.' ] @formatter = formatter end

def output_report @formatter.output_report( @title, @text ) endend

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 tymzadaniem jest formatowanie raportu). Wszystkie obiekty strategii nie tylko realizuj� tosamo zadanie, ale te� obs�uguj� identyczny interfejs. W prezentowanym przyk�adzieten wspólny interfejs ogranicza si� do metody output_report. Skoro wszystkie obiektystrategii z zewn�trz wygl�daj� tak samo, u�ytkownik strategii (nazywany przez Band�Czworga klas� kontekstu — ang. context class) mo�e je traktowa� jak wymienneelementy. 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 projektowyStrategy

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�egotekstu. Gdyby�my zastosowali wzorzec Strategy w systemie obliczaj�cym wysoko��podatku dochodowego, mogliby�my u�y� jednej strategii do wyznaczania podatkup�aconego przez etatowego pracownika i innej do obliczania podatku uiszczanegoprzez pracownika zatrudnionego na podstawie umowy o dzie�o.

Page 12: Ruby. Wzorce projektowe

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� naszegokodu dzi�ki wyodr�bnieniu zbioru strategii poza klas� g�ówn�. Wzorzec Strategyzwalnia klas� Report z jakiejkolwiek odpowiedzialno�ci czy cho�by konieczno�cisk�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 programunie stanowi �adnego problemu. Wystarczy wymieni� obiekt strategii:

report = Report.new(HTMLFormatter.new)report.output_report

report.formatter = PlainTextFormatter.newreport.output_report

Wzorzec projektowy Strategy ma jedn� cech� wspóln� ze wzorcem Template Method:oba wzorce umo�liwiaj� nam koncentrowanie decyzji o wyborze sposobu realizacjizlecanych 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 czasiewykonywania programu.

WSPÓ�DZIELENIE DANYCHPRZEZ 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 dowyboru dwa rozwi�zania.

Po pierwsze, mo�emy konsekwentnie stosowa� dotychczasowe rozwi�zanie polegaj�cena 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�rednictwemargumentów wywo�a metody output_report. Przekazywanie kompletnych danychma t� zalet�, �e pozwala skutecznie izolowa� kontekst od obiektów strategii. Strategiemaj� 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.

Page 13: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1105

Po drugie, mo�emy przekazywa� dane z kontekstu do strategii w formie referencji dosamego obiektu kontekstu. Obiekt strategii mo�e wówczas uzyskiwa� niezb�dne daneza 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) endend

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�' endend

class HTMLFormatter < Formatter def output_report(context) puts('<html>') puts(' <head>') puts(" <title>#{context.title}</title>") puts(' </head>') puts(' <body>') context.text.each do |line| puts(" <p>#{line}</p>") end puts(' </body>') puts('</html>') endend

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�kszamyryzyko wzajemnego uzale�nienia klasy kontekstu i klas strategii.

Page 14: Ruby. Wzorce projektowe

106 Cz��� II • WZORCE PROJEKTOWE W J�ZYKU RUBY

JESZCZE RAZ O KACZYM TYPOWANIUPrzyk�adow� aplikacj� generuj�c� raporty, któr� pos�ugiwali�my si� w tym rozdziale,zbudowano zgodnie z zaleceniami Bandy Czworga odno�nie do wzorca projektowegoStrategy. 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 Formatterw praktyce nie realizuje �adnych dzia�a — istnieje tylko po to, by definiowa� wspólnyinterfejs wszystkich klas formatuj�cych. Wspomniany problem w �aden sposób niewp�ywa na formaln� poprawno�� naszego kodu — tak napisany program po prostudzia�a. Z drugiej strony takie rozwi�zanie jest sprzeczne z przyj�t� w j�zyku Rubyfilozofi� tzw. kaczego typowania. Skoro klasy HTMLFormatter i PlainTextFormatterimplementuj� 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) endend

class HTMLFormatter def output_report(context) puts('<html>') puts(' <head>') # Wy�wietla pozosta�e dane tego obiektu…

puts(" <title>#{context.title}</title>") puts(' </head>') puts(' <body>') context.text.each do |line| puts(" <p>#{line}</p>") end puts(' </body>') puts('</html>') endend

Page 15: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1107

class PlainTextFormatter def output_report(context) puts("***** #{context.title} *****") context.text.each do |line| puts(line) end endend

Je�li porównamy ten kod z poprzedni� wersj�, przekonamy si�, �e rezygnacja z klasybazowej Formatter nie wymaga�a zbyt wielu dodatkowych zmian. Dzi�ki dynamicznejkontroli typów nadal mo�emy generowa� prawid�owe raporty. Chocia� obie wersjedzia�aj� zgodnie z za�o�eniami, do �wiata Ruby du�o lepiej pasuje model pozbawionyklasy bazowej Formatter.

OBIEKTY PROC I BLOKI KODUOkazuje si�, �e eliminacja klasy bazowej nie jest jedynym sposobem dostosowaniawzorca projektowego Strategy do charakteru j�zyka programowania Ruby. Zanimjednak 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 czasuna 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�ynie mamy problemu z wyodr�bnianiem danych poza obiekt — mo�emy na przyk�aduzyska� warto�� zmiennej @text obiektu raportu i przekazywa� j� dalej niezale�nieod 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. Takieprzekonanie oczywi�cie nie znajduje potwierdzenia w praktyce. Co w takim raziepowinni�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�owemend 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).

Page 16: Ruby. Wzorce projektowe

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. Kodreprezentowany przez obiekt Proc mo�emy wykona�, wywo�uj�c metod� call (trudnosobie wyobrazi� lepsz� nazw�). Je�li w przedstawionym przyk�adzie wywo�amy metod�call obiektu Proc:

hello.call

otrzymamy komunikaty:

WitajJestem 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 momencietworzenia 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.callputs(name)

Kiedy wykonamy ten kod, zmiennej name w pierwszej kolejno�ci zostanie przypisany�acuch "Jan", po czym (po wywo�aniu obiektu Proc) warto�� tej zmiennej zostaniezast�piona przez �acuch "Maria".

Oznacza to, �e ostatecznie Ruby wy�wietli �acuch "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�yciatej 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� doblokó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.

Page 17: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1109

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 — abyzwróci� warto�� z poziomu takiego obiektu, wystarczy si� upewni�, �e jest ona wy-znaczana przez jego ostatnie wyra�enie. Wszelkie warto�ci zwracane przez obiektyProc 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 nawiasamiokr�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 ichiloczyn 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:

60500

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 koduza pomoc� s�owa kluczowego yield. Poni�ej zdefiniowano przyk�adow� metod�wy�wietlaj�c� komunikat, wykonuj�c� otrzymany blok kodu i wy�wietlaj�c� kolejnykomunikat:

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óbdopisujemy blok kodu na koniec wywo�ania naszej metody:

Page 18: Ruby. Wzorce projektowe

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 yieldWitajPrzybywam do Ciebie z wn�trza bloku koduPo wykonaniu yield

Je�li przekazany blok kodu sam otrzymuje jakie� parametry, nale�y je przekaza� zapo�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 yieldWitaj z wn�trza bloku koduParametr x ma warto�� 24Po wykonaniu yield

W niektórych przypadkach warto zdefiniowa� wprost parametr reprezentuj�cy blokkodu — 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� specjalnyparametr na kocu listy parametrów tej metody. Tak przekazany parametr (poprze-dzony znakiem &) zostanie przypisany obiektowi Proc utworzonemu na podstawiebloku kodu do��czonego do wywo�ania danej metody. Oznacza to, �e odpowiednikiemprzedstawionej powy�ej metody run_it_with_parameters b�dzie nast�puj�cakonstrukcja:

def run_it_with_parameter(&block) puts("Przed wykonaniem yield") block.call(24) puts("Po wykonaniu yield")end

Page 19: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1111

Symbol & mo�na z powodzeniem stosowa� tak�e w przeciwnym kierunku. Gdyby�myumie�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 wymaganegobloku, 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 ANALIZAKILKU 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óryopakowano w formie obiektu. Przytoczona definicja brzmi znajomo — obiekt Procbywa 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 poprzedzeniaparametru przekazywanego na wej�ciu metody initialize symbolem & i zmianynazwy 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 ) endend

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('<html>') puts(' <head>') puts(" <title>#{context.title}</title>") puts(' </head>') puts(' <body>') context.text.each do |line|

Page 20: Ruby. Wzorce projektowe

112 Cz��� II • WZORCE PROJEKTOWE W J�ZYKU RUBY

puts(" <p>#{line}</p>" ) end puts(' </body>')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 konstruktorklasy Report oczekuje bloku kodu, tworz�c nowy obiekt tej klasy musimy poprze-dzi� wspomniany obiekt Proc znakiem &:

report = Report.new &HTML_FORMATTERreport.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 koduna wej�ciu istniej�cej metody. Mo�emy zaimplementowa� na przyk�ad mechanizmformatuj�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) endend

Programistom nieprzyzwyczajonym do tego rodzaju konstrukcji bloki kodu mog�si� wydawa� dziwaczne. Z drugiej strony powinni�my pami�ta�, �e proponowanatechnika implementacji wzorca Strategy umo�liwia zast�pienie klas� kontekstu, klas�bazow� strategii i wiele konkretnych strategii (wraz ze wszystkimi niezb�dnymiobiektami) 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 koca. 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� interfejsuz�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�myrozwa�y� u�ycie bloków kodu.

U�YWANIE I NADU�YWANIEWZORCA PROJEKTOWEGO STRATEGY

Najcz�stsz� przyczyn� b��dnego implementowania wzorca projektowego Strategyjest niew�a�ciwe definiowanie interfejsu pomi�dzy kontekstem a strategiami. Musimypami�ta�, �e naszym celem jest wyodr�bnienie kompletnego, spójnego i mniej lub

Page 21: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1113

bardziej autonomicznego zadania poza obiekt kontekstu i delegowanie go do obiektustrategii. 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 kontekstz pierwsz� strategi� na tyle mocno, �e uzupe�nienie projektu o drug�, trzeci� i kolejnestrategie oka�e si� niemo�liwe.

WZORZEC STRATEGYW PRAKTYCZNYCH ZASTOSOWANIACH

Narz�dzie rdoc (do��czane do dystrybucji j�zyka Ruby) zawiera wiele mechanizmówopracowanych na podstawie klasycznego, zaproponowanego przez Band� Czworgai opartego na klasach wzorca projektowego Strategy. Zadaniem tego narz�dzia jestgenerowanie 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�dzierdoc 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�emywybra� 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 tychformatów wyj�ciowych tak�e jest obs�ugiwany przez wyspecjalizowan� strategi�.Relacje ��cz�ce poszczególne klasy strategii programu rdoc dobrze ilustruj� ogólnepodej�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�cenarz�dzia rdoc

Jak wida� na rysunku 4.2, istniej� cztery powi�zane ze sob� strategie formatowaniadanych wyj�ciowych (okre�lanych w programie rdoc mianem generatorów) i jednastrategia autonomiczna. Wszystkie cztery powi�zane strategie generuj� dokumentacj�w podobnym formacie — znane wszystkim konstrukcje <co�tam> otoczone nawiasami

Page 22: Ruby. Wzorce projektowe

114 Cz��� II • WZORCE PROJEKTOWE W J�ZYKU RUBY

ostrymi </co�tam>3. Ostatnia strategia generuje dane wyj�ciowe na potrzeby poleceniari j�zyka Ruby, które nie przypominaj� ani kodu XML-a, ani kodu HTML-a. Jakwynika z diagramu UML przedstawionego na rysunku 4.2, relacje ��cz�ce poszczególneklasy 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 RIGeneratorgeneruje 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 jednejnadklasy 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 strategiimamy 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 schematuporz�dkowania elementów? Jak nale�a�oby na przyk�ad posortowa� �acuchy wed�ugd�ugo�ci? Wystarczy przekaza� strategi� porównywania obiektów w formie blokukodu:

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�lipierwszy 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 koduprzypomina zachowanie operatora <=>.

PODSUMOWANIEWzorzec projektowy Strategy reprezentuje nieco inn�, opart� na delegowaniu zadapropozycj� rozwi�zywania tego samego problemu, który jest równie� rozwi�zywanyprzez wzorzec Template Method. Zamiast upychania zmiennych cz��ci algorytmuw podklasach, implementujemy ka�d� z wersji tego algorytmu w odr�bnym obiekcie.Mo�emy nast�pnie urozmaica� dzia�ania tego algorytmu przez wskazywanie obiektowikontekstu ró�nych obiektów strategii. Oznacza to, �e o ile jedna strategia na przyk�adgeneruje 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.

Page 23: Ruby. Wzorce projektowe

Rozdzia� 4. • ZAST�POWANIE ALGORYTMU STRATEGI 1115

w formacie PDF; podobnie, jedna strategia mo�e wyznacza� wysoko�� podatku od-prowadzanego przez pracownika etatowego, by inna wylicza�a podatek nale�ny odpracownika 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, albopo prostu przekazywa� obiektowi strategii referencj� do ca�ego obiektu kontekstu.

Bloki kodu j�zyka Ruby, które w istocie maj� posta� kodu opakowywanego w ramachtworzonego 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�lonegozadania. Okazuje si� jednak, �e wykonanie tego zadania wymaga od kontekstuskorzystania z pomocy innego obiektu (okre�lanego mianem strategii). Z bardzopodobnym modelem mamy do czynienia w przypadku wzorca projektowego Ob-server (obserwatora), gdzie obiekt realizuj�cy pewne zadania kieruje wywo�ania dodrugiego obiektu, bez którego jego funkcjonowanie by�oby niemo�liwe.

Okazuje si�, �e jedyn� ró�nic� dziel�c� oba te wzorce jest intencja programisty. Celemwzorca projektowego Strategy jest dostarczenie obiektowi kontekstu innego obiektu,który „wie”, jak wykona� okre�lon� wersj� algorytmu. Zupe�nie inny cel przy�wiecaprogrami�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, �eb�dzie to kolejny rozdzia�).