puts('Witaj z wntrza bloku kodu')puts("Parametr x ma warto #{x}")endwywietli nastpujce komunikaty:Przed wykonaniem yieldWitaj z wntrza bloku...

Pokaż mi serce nie opętane zwodniczymi marzeniami, a pokażę ci człowieka szczęśliwego.

W tym celu naley umieci 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 doczonego do wywoania danej metody. Oznacza to, e odpowiednikiem przedstawionej powyej metody run_it_with_parameters bdzie nastpujca konstrukcja:
def run_it_with_parameter(&block)
puts("Przed wykonaniem yield")
block.call(24)
puts("Po wykonaniu yield")
end
Rozdzia 4. • ZASTPOWANIE ALGORYTMU STRATEGI
111
Symbol & mona z powodzeniem stosowa take w przeciwnym kierunku. Gdybymy umiecili obiekt Proc w zmiennej i chcieli go przekaza na wejciu metody oczekujcej bloku kodu, moglibymy przekonwertowa ten obiekt do postaci wymaganego bloku, poprzedzajc odpowiedni parametr wanie 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ówic, strategi mona postrzega jako blok wykonywalnego kodu, który „wie”, jak zrealizowa okrelone zadanie (np. formatowanie tekstu) i który opakowano w formie obiektu. Przytoczona definicja brzmi znajomo — obiekt Proc bywa okrelany wanie jako fragment kodu opakowany w formie obiektu.
Wrómy teraz do naszego przykadowego systemu formatujcego raporty, gdzie zastosowanie strategii w formie obiektu Proc okazuje si wyjtkowo proste. Zmiany, które musimy wprowadzi w kodzie klasy Report, ograniczaj si do poprzedzenia parametru przekazywanego na wejciu metody initialize symbolem & i zmiany nazwy wywoywanej metody z output_report na call:
class Report
attr_reader :title, :text
attr_accessor :formatter
def initialize(&formatter)
@title = 'Raport miesiczny'
@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 waciwe formatowanie. Musimy teraz stworzy obiekty Proc zamiast egzemplarzy naszych wyspecjalizowanych klas formatujcych:
HTML_FORMATTER = lambda do |context|
puts('')
puts(' ')
puts(" #{context.title}") puts(' ')
puts(' ')
context.text.each do |line|
112
Cz II • WZORCE PROJEKTOWE W JZYKU RUBY
puts("

#{line}

" )
end
puts(' ')
puts
Skoro dysponujemy ju kodem formatujcym w formie obiektu Proc, moemy przystpi do tworzenia raportów. Poniewa dysponujemy obiektem Proc, a konstruktor klasy Report oczekuje bloku kodu, tworzc 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 koniecznoci definiowania specjalnych klas dla poszczególnych strategii — wystarczy opakowa kod w ramach obiektu Proc. Co wicej, stosujc t technik moemy tworzy strategie niemal z niczego, przekazujc bloki kodu na wejciu istniejcej metody. Moemy zaimplementowa na przykad mechanizm formatujcy raporty tekstowe w formie nastpujcego 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 powinnimy pamita, e proponowana technika implementacji wzorca Strategy umoliwia zastpienie klas kontekstu, klas
bazow strategii i wiele konkretnych strategii (wraz ze wszystkimi niezbdnymi obiektami) pojedyncz klas kontekstu i kilkoma blokami kodu.
Czy to oznacza, e powinnimy raz na zawsze zapomnie o strategiach implementowa-nych w postaci odrbnych 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 moemy wy-woywa dla obiektów Proc. Jeli implementowane strategie wymagaj interfejsu zoonego z wikszej liczby metod, nie mamy wyboru — musimy skorzysta z tra-dycyjnych klas. Jeli jednak interfejs strategii jest prosty, koniecznie powinnimy rozway uycie bloków kodu.
UYWANIE I NADUYWANIE
WZORCA PROJEKTOWEGO STRATEGY
Najczstsz przyczyn bdnego implementowania wzorca projektowego Strategy jest niewaciwe definiowanie interfejsu pomidzy kontekstem a strategiami. Musimy pamita, e naszym celem jest wyodrbnienie kompletnego, spójnego i mniej lub
Rozdzia 4. • ZASTPOWANIE ALGORYTMU STRATEGI
113
bardziej autonomicznego zadania poza obiekt kontekstu i delegowanie go do obiektu strategii. Powinnimy zwraca szczególn uwag zarówno na szczegóy interfejsu
czcego kontekst ze strategi, jak i na zwizki wystpujce pomidzy obiema stro-nami tej relacji. Stosowanie wzorca Strategy bdzie bezcelowe, jeli zwiemy kontekst z pierwsz strategi na tyle mocno, e uzupenienie projektu o drug, trzeci i kolejne strategie okae si niemoliwe.
WZORZEC STRATEGY
W PRAKTYCZNYCH ZASTOSOWANIACH
Narzdzie rdoc (doczane do dystrybucji jzyka Ruby) zawiera wiele mechanizmów opracowanych na podstawie klasycznego, zaproponowanego przez Band Czworga i opartego na klasach wzorca projektowego Strategy. Zadaniem tego narzdzia jest generowanie dokumentacji na podstawie kodu ródowego. rdoc oferuje moliwo
dokumentowania zarówno programów napisanych w Ruby, jak i programów opracowanych w C i (ratunku!) programów stworzonych w jzyku FORTRAN. Narzdzie rdoc wykorzystuje wzorzec Strategy do obsugi poszczególnych jzyków programowania — kady analizator skadniowy (waciwy dla jzyków C, Ruby i FORTRAN) ma posta strategii stworzonej z myl o innych danych wejciowych.
Copyright (c) 2009 Pokaż mi serce nie opętane zwodniczymi marzeniami, a pokażę ci człowieka szczęśliwego. | Powered by Wordpress. Fresh News Theme by WooThemes - Premium Wordpress Themes.