You are on page 1of 45

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl

Head First Design


Patterns. Edycja polska
Autorzy: Eric Freeman, Elisabeth Freeman
Tumaczenie: Pawe Koronkiewicz (wprowadzenie,
rozdz. 18), Grzegorz Kowalczyk (rozdz. 914)
ISBN: 83-7361-792-2
Tytu oryginau: Head First Design Patterns
Format: 200230, stron: 656

Poznaj w niekonwencjonalny sposb zasady stosowania wzorcw projektowych


Dowiedz si, czym s wzorce projektowe
Poznaj typy wzorcw projektowych
Zastosuj wzorce projektowe w praktyce
Naucz si projektowa aplikacje w oparciu o wzorce projektowe
Otwrz swj umys. Poznaj wszystko, co jest zwizane z wzorcami projektowymi,
w sposb gwarantujcy szybkie i skuteczne opanowanie zasad ich stosowania.
Zapomnij o listingach liczcych tysice linii, dugich i nucych opisach teoretycznych
oraz rozbudowanych schematach zalenoci. Czytajc ksik Head First Design
Patterns. Edycja polska, poznasz wzorce projektowe w inny sposb. Wzorce projektowe
to gotowe opisy rozwiza najczciej spotykanych zagadnie zwizanych z tworzeniem
oprogramowania. Aby je prawidowo stosowa, naley pozna zaoenia, na podstawie
ktrych zostay stworzone, oraz nauczy si implementowa je we waciwy sposb.
Dziki ksice Head First Design Pattern. Edycja polska wszystkie pojcia zwizane
ze wzorcami projektowymi przestan by dla Ciebie wiedz tajemn. Autorzy ksiki,
wykorzystujc najnowsze elementy teorii uczenia, przedstawi Ci wszystkie zagadnienia
niezbdne do rozpoczcia projektowania i tworzenia aplikacji w oparciu o wzorce
projektowe. Poznasz najczciej stosowane wzorce projektowe, metody ich
implementacji i zadania, do jakich s przeznaczone. Jednak, co najwaniejsze,
nauczysz si stosowa t wiedz w praktyce.
Cele stosowania wzorcw projektowych
Zaoenia, na ktrych opieraj si wzorce projektowe
Najwaniejsze i najczciej wykorzystywane wzorce projektowe
Przechowywanie i prezentacja danych
Mechanizm RMI
Wzorzec MVC
Implementacja wzorcw projektowych w aplikacjach
Przekonaj si, e nowoczesne metody nauczania mog zmieni rwnie sposb
poznawania nowoczesnych technik programistycznych.

Spis treci (skrcony)


Wprowadzenie

21

1. Witamy w krainie wzorcw projektowych: wprowadzenie

33

2. Jak sprawi by Twoje obiekty


byy zawsze dobrze poinformowane: Wzorzec Obserwator

67

3. Dekorowanie zachowania obiektw: Wzorzec Dekorator

109

4. Pizzeria zorientowana obiektowo: Wzorzec Fabryka

139

5. Obiekty jedyne w swoim rodzaju: Wzorzec Singleton

197

6. Hermetyzacja wywoa: Wzorzec Polecenie

217

7. Zdolno do adaptacji: Wzorce Adapter oraz Fasada

259

8. Hermetyzacja algorytmw: Wzorzec Metoda Szablownowa

297

9. Zarzdzanie kolekcjami: Wzorce Iterator i Kompozyt

335

10. Stan obiektu: Wzorzec Stan

403

11. Kontrola dostpu do obiektu: Wzorzec Proxy

447

12. czenie wzorcw: Wzorce zoone

517

13. Wzorce projektowe w praktyce: Nowe ycie z wzorcami

595

14. Dodatek: inne wzorce

629

Skorowidz

649

Spis treci (na serio)


Wprowadzenie
Twj mzg jest skoncentrowany na wzorcach projektowych.
W tym rozdziale Ty starasz si czego dowiedzie, a Twj mzg robi Ci przysug i nie przykada si
do zapamitywania zdobywanej wiedzy. Twj mzg myli sobie: Lepiej zostawi miejsce w pamici
na bardziej istotne informacje, na przykad: jakich dzikich zwierzt naley unika bd czy jedenie nago
na snowboardzie jest dobrym pomysem. A zatem, w jaki sposb moesz przekona swj mzg, e Twoje
ycie zaley od poznania wzorcw projektowych?

Dla kogo przeznaczona jest ta ksika?

22

Wiemy take, co sobie myli Twj mzg

23

Metapoznanie

25

Zmu swj mzg do posuszestwa

27

Zesp recenzentw technicznych

30

Podzikowania

31

Wprowadzenie do wzorcw projektowych


Witamy w krainie wzorcw projektowych
Kto rozwiza ju Twoje problemy. W tym rozdziale dowiesz si, dlaczego (i w jaki
sposb) moesz wykorzysta wiedz i dowiadczenia zdobyte przez innych projektantw i programistw,
ktrzy podczas pracy nad rnymi projektami zmuszeni byli wstpi na pen zdradliwych puapek ciek
i co najwaniejsze udao im si przey tak wypraw. Zanim dobrniemy do koca rozdziau, rzucimy
okiem na sposoby wykorzystywania wzorcw projektowych i przedstawimy ich zalety, poznamy kilka
podstawowych zasad projektowania zorientowanego obiektowo, a take omwimy sposb dziaania
przykadowego wzorca. Najlepsz metod zastosowania wzorca jest zaadowanie go bezporednio
do Twojego mzgu, a nastpnie zlokalizowanie obszarw w obrbie projektowanych rozwiza oraz
istniejcych aplikacji, w ktrych moesz je zastosowa. Pracujc z wzorcami projektowymi, zamiast
wielokrotnego wykorzystywania tych samych fragmentw kodu, wielokrotnie wykorzystujesz swoje
dowiadczenia.

Pamitaj,
opanowanie takich
zagadnie, jak
abstrakcyjno, dziedziczenie
i polimorfizm, nie zrobi jeszcze
z Ciebie dobrego projektanta
systemw zorientowanych
obiektowo. Prawdziwy guru zawsze
myli o stworzeniu elastycznego
projektu, ktry bdzie atwy
do serwisowania i bdzie
sobie w stanie poradzi ze
zmieniajcymi si
warunkami.

Prosta aplikacji o nazwie SymulatorKaczki

34

Jacek rozmyla o dziedziczeniu

37

A moe by tak interfejs?

38

Jedyny pewny element w procesie tworzenia oprogramowania

40

Oddzielanie tego, co si zmienia, od tego, co pozostaje niezmienione

42

Projektowanie zachowania Kaczki

43

Testowanie kodu klasy Kaczka

50

Dynamiczne ustawianie zachowania

52

Wielki diagram ukrytych zachowa

54

Relacja MA moe by lepsza ni JEST

55

Rozmawiajc o wzorcach projektowania

56

Potga wsplnego sownika wzorcw

60

W jaki sposb mog wykorzystywa wzorce projektowe?

61

Twoja skrzynka narzdziowa

64

Rozwizania wicze

66

Encaps

y beh
ulated

ZG

avior

Twj M

ace>>

<<interf

FlyBeh

avior

y()

ay
FlyNoW

FlyWith

Duck

ying

FlyBeha

ehavior
QuackB

ulated

Encaps

swim()

)
display(
Quack()
perform
Fly()
perform
)
ehavior(
setFlyB
ior()
kBehav
setQuac
e methduck-lik
// OTHER

<<interf

quack
ior

MuteQuack

Squeak

Quack
Decoy

Object
that holds
state
Mallard

Redhead

Duck

Duck

{
display()
}
a redhead
// looks like

{
display()
}
a mallard
// looks like

Su

bje

int

t
ct Objec

Rubber

behavio

ace>>

QuackBehav
quack()

Duck

Duck

){
display(
like a decoy
// looks

{
display()
ck }
a rubberdu
// looks like

{
quack)
nts duck
// impleme
g
quackin

{
quack()
duckie
// rubber

{
quack()
- cant
// do nothing
quack!

squeak

OBSERWATOR

8
8
8

Dog Objec

8
Duck Objec

Mo

Automatic update/notication

Cat Object

ct
use Obje
Observers

oller

Contr

Depend
Objects ent

Grupa wzorcw projektowych

y() {
- cant y!
// do nothing

y() {
nts duck
// impleme

vior;
vior yBeha
ehavquackB

Client

Wings

est
Requ

View

MVC
l
Mode

az ju cakiem
Twj Kod, ter
cony poprzez
nowy i wzboga
wzorcw
zastosowanie
projektowych.

Wzorzec Obserwator

Jak sprawi, by Twoje obiekty byy


zawsze dobrze poinformowane
Nie przegap okazji, kiedy dzieje si co naprawd ciekawego!
Przedstawimy Ci wzorzec, ktry potrafi poinformowa inne obiekty o tym, e wydarzyo si co, czym
powinny si zaj. Co ciekawe, obiekty mog nawet samodzielnie decydowa w czasie dziaania programu
o tym, czy chc by informowane o takich wydarzeniach. Wzorzec Obserwator jest jednym z najczciej
wykorzystywanych wzorcw w pakiecie JDK (ang. Java Development Kit) a co najwaniejsze, jest wrcz
niewiarygodnie uyteczny. W niniejszym rozdziale rzucimy rwnie okiem na relacje typu jeden-do-wielu
oraz tzw. lune zwizki (tak, to prawda, napisalimy lune zwizki). Korzystajc z wzorca Obserwator,
z pewnoci odmienisz swoje ycie.

Abstr

ja
Hermetyzac
m
fiz
Polimor

g ra m
R eg u y p ro
o
ob ie kt ow eg

ow a ni a

ie

Dziedziczen

o
obiektoweg
ramowania
Reguy prog
ienia.
to, co si zm
rmetyzacji
he
aj
w
da
Pod
dziczenie.
cj nad dzie
aj kompozy
Przedkad
ejsw,
zeniu interf
si na twor
uj
tr
en
nc
ko
S
entacji.
a nie implem
h
ty, w ktryc to
orzy projek
i, o ile
Staraj si tw b luno powizane
ze so
zajemnie.
obiekty s
na siebie w
e oddziauj
moliwe, ni

Aplikacja sprawdzajca warunki pogodowe

69

Spotkanie z wzorcem Obserwator

74

Wydawca + Prenumerator = wzorzec Obserwator

75

Piciominutowe przedstawienie obserwowany kontra obserwujcy

78

Denicja wzorca Obserwator

81

Sia lunych zalenoci

83

Projektowanie stacji meteorologicznej

86

Implementacja stacji meteorologicznej

87

Java zastosowanie wbudowanego wzorca Obserwator

94

Ciemna strona klasy java.util.Observable

101

Twoja skrzynka narzdziowa

104

Rozwizania wicze

107

RELACJA JEDEN-DO-WIELU

Obiekt, ktrego stan


jest obserwowany

Ob

iekt

int

an y

obserwo

8
8

Obie

8
Obie

Automatyczna aktualizacja
(powiadamianie)

kt Pies

kt Kaczk

Obie

Obie

kt Kot

kt Mysz

Obiekty obserwujce
(Observers)

Ob iek ty za le ne

Pod st a w y
ow eg o
a ni a ob ie kt
p ro g ra m ow
akcyjno

Wzorzec Dekorator
Dekorowanie zachowania obiektw
W zasadzie niniejszy rozdzia moemy rwnie dobrze zatytuowa
Otwieranie oczu programistom z nadmiernymi skonnociami
do naduywania dziedziczenia. W tym rozdziale sprbujemy krytycznie przyjrze si
zwyczajowym skonnociom do naduywania mechanizmu dziedziczenia oraz nauczymy Ci sposobw
dekorowania zachowania klas w czasie dziaania programu przy uyciu pewnej formy kompozycji
obiektw. Dlaczego? Po zapoznaniu si z technikami dekoracji zachowania klas bdziesz mg wyposaa
swoje (i nie tylko) obiekty w nowe moliwoci bez koniecznoci dokonywania jakichkolwiek modyfikacji
w kodzie klas podstawowych.

Zawsze sdziem,
e prawdziwi mczyni tworz
podklasy dla wszystkiego, co si tylko
do tego nadaje. Tak byo do czasu,
gdy dowiedziaem si o korzyciach,
jakie daje moliwo rozszerzania
moliwoci aplikacji na poziomie
dziaania, a nie kompilacji. A teraz
spjrzcie tylko na mnie!

Witamy w Star Caf

110

Regua otwarte-zamknite

116

Spotkanie z wzorcem Decorator

118

Konstruowanie zamwienia przy uyciu Dekoratorw

119

Denicja wzorca Decorator

121

Dekorujemy nasze Napoje

122

Tworzymy kod aplikacji Star Caf

125

Dekoratory w wiecie rzeczywistym:


obsuga wejcia-wyjcia w jzyku Java

130

Tworzenie wasnych dekoratorw obsugi wejcia-wyjcia

132

Twoja skrzynka narzdziowa

135

Rozwizania wicze

136

Wzorzec Fabryka
Pizzeria zorientowana obiektowo
Przygotuj si do stworzenia kilku projektw, w ktrych zastosujemy
lune powizania pomidzy poszczeglnymi obiektami. Stworzenie
nowego obiektu to duo wicej ni tylko proste zastosowanie operatora new. Niebawem przekonasz si,
e proces ten jest operacj, ktra nie zawsze powinna by publicznie dostpna, a co wicej, jest operacj,
ktra czsto moe prowadzi do powanych problemw z powizaniami midzyobiektowymi. A tego by
nie chcia, prawda? Przekonaj si, w jaki sposb wzorzec Factory moe uratowa Ci z takiej opresji.

Klientami fabryki abstrakcyjnej s


dwa obiekty naszej klasy Pizzeria,
WoskaPizzeria i Amerykaska
Pizzeria.
WoskaPizzeria
utwrzPizza()

Klasa abstrakcyjna FabrykaSkadnikwPizzy jest


interfejsem, ktry okrela, w jaki sposb powinna
by tworzona rodzina spokrewnionych produktw
wszystkie skadniki, ktre s niezbdne do
zrobienia pizzy.

<<interfejs>>
Ciasto

GrubeChrupkieCiasto

CienkieChrupkieCiasto

<<interfejs>>
FabrykaSkadnikwPizzy
utwrzCiasto()
utwrzSos()
utwrzSer()
utwrzWarzywa()
utwrzPepperoni()
utwrzMae()

<<interfejs>>
Sos

SosPomidorowy

WoskaFabrykaSkadnikwPizzy
utwrzCiasto()
utwrzSos()
utwrzSer()
utwrzWarzywa()
utwrzPepperoni()
utwrzMae()

AmerykaskaFabryka
SkadnikwPizzy
utwrzCiasto()
utwrzSos()
utwrzSer()
utwrzWarzywa()
utwrzPepperoni()
utwrzMae()

SosMarinara

<<interfejs>>
Ser

SerMozzarella

SerReggiano

<<interfejs>>
Mae

Zadaniem fabryk rzeczywistych


jest wytwarzanie odpowiednich
skadnikw pizzy. Kada
fabryka wie, w jaki sposb
naley utworzy skadniki
odpowiednie dla danego regionu.

MrooneMae

Kada fabryka wytwarza rne


implementacje tej samej rodziny produktw.

10

wieeMae

Kiedy widzisz nowy obiekt, myl o nim jako o konkretnym

140

Pizza w Obiektowie

142

Hermetyzacja procesu tworzenia obiektw

144

Budujemy prost fabryk pizzy

145

Tworzymy denicj wzorca Simple Factory

147

Nowa struktura Pizzerii

150

Zezwalamy klasom podrzdnym na podejmowanie decyzji

151

Tworzymy Pizzeri

153

Deklarowanie metody typu Factory (fabryka)

155

Spotkanie z wzorcem Metoda Fabrykujca

161

Rwnolega hierarchia klas

162

Denicja wzorca Metoda Fabrykujca

164

Pizzeria mocno uzaleniona

167

Sprawdzamy zalenoci pomidzy obiektami

168

Zastosowanie reguy DIP

170

A w midzyczasie, na zapleczu Pizzerii

174

Rodziny skadnikw

175

Budujemy fabryki skadnikw pizzy

176

Fabryka Abstrakcyjna

183

Za kulisami

184

Denicja wzorca Fabryka Abstrakcyjna

186

Porwnanie Metody Fabrykujcej oraz Fabryki Abstrakcyjnej

190

Twoja skrzynka narzdziowa

192

Rozwizania wicze

193

Wzorzec Singleton
Obiekty jedyne w swoim rodzaju
Kolejnym przystankiem w naszej podry jest wzorzec Singleton,
czyli nasza przepustka do kreowania jedynych w swoim rodzaju
obiektw, posiadajcych tylko jedn instancj. By moe ucieszysz si na wie
o tym, e Singleton jest najprostszym z istniejcych wzorcw projektowych (przynajmniej pod wzgldem
kategorii stopnia zoonoci jego diagramu klas); jak by na to nie patrze, jego diagram skada si tylko
z jednej klasy! Ale nie wpadaj w eufori; niezalenie od prostoty diagramu klas tego wzorca na drodze
prowadzcej do jego implementacji napotkamy cakiem sporo wybojw i dziur. Lepiej zapnij mocno pasy
to nie bdzie takie proste jakby mogo si wydawa.

Hershey, PA

Jeden i tylko jeden

198

May Singleton

199

Analiza klasycznej implementacji wzorca Singleton

201

Wyznania obiektu Singleton

202

Fabryka czekolady

203

Denicja wzorca Singleton

205

Uuups, mamy problem

206

Zosta wirtualn maszyn Java

207

Jak sobie radzi z wielowtkowoci?

208

Wzorzec Singleton pytania i odpowiedzi

212

Twoja skrzynka narzdziowa

214

Rozwizania wicze

216

iektowego
mowania ob
ra
og
pr
e
rc
nWzo
konuje relacj jede

, doiektami
y ob
dzw
algoryitm
zmieielaniniae
zye.dz
ymob
iennkt
fininiuyje pomaj si na
eiepr
dedz
onmeraicwnyzn
finiuje ro
yb
j
w
dy
st
s do
y
na
erwdeator wodujpo
e
ed
a
orrfmyejda
ki
e,
al
otety
StrateOgybs
go
inat
, e
or
zw
a
ne
aj
b
ek
cz
st
da
D
os
po
y
.
i
ar
zo

j
sp
ji
st
e
a
ac
or
ki
ac
do
n
ik
ta
yf
ch
leow
w at
od
ekor
poyczwh alajc
hjnyzaaza
D
ielu
kt
nibe,rfzaejlesn
udz
na
yc
iecy
lute
-wyz
ajebs
wak
tm
ichze
doet
alow
ich herm
trmob
no
yc
ry
i
go
in
zw
on
ie
e.
go
je
A
ni
po
al
dz
an
ie
iu
a
w
kt
yma tylko
je
tk
gy
go
ie
ow
yk
fin
re
ys
te
dn
te
da
ob
liz de
ok
asdrz
ydz
raan
uszbr
k
sp
kl
ua
Fa
w
r
m
,
St
ja
h
kt
in
a
kt
j,
ne
ic
po
za
ec
ia
c
a,
a
te
da
st
m
rz
ie
uj
ro
ni
om
nt
j
do
ie
zo
zn

yk
ie
klaet
W sw
yc
on
reallaanaklasklasa bdz .
bny
at
Fabr
okzw
do
mca
eiod
ach
zeporz
nino
to
ni
zseci
od
aupo
ze
ro, alo
or
iewzn
M
ez
ne
da
ny
ni
tw
nieldo
iocz
ko
u ia
obalny
mtye
zac
asal
orzo
ktec
iezn
ianinbe
mw
eznob
pewnia,ktezostanieiektutuwi za
pow
algorytm
pewnia gl
iezakt
ze
or
o za
dnieak
iestancj ob
leton ejklza
jesieb
naobwtw
ob
ng
c
od
y
Si
uj
as
er
of
a.
powiedzialn
in
ki
od

ja
.
je
,
uyw
dn
ch
zu
a
je
ty
w
ka
.
ie
is
do
ze
zywdecy i wyczn y Methodjpr
alno
rzec
instancji.
funkcjon
ecnkFatctdoorstpu do klteas podrzdnych.
Wzorzpu
do
w
kt
ie
ob
e
tworzeni

11

Wzorzec Polecenie

Hermetyzacja wywoa
W niniejszym rozdziale przeniesiemy hermetyzacj na
zupenie nowy poziom: mamy zamiar dokona hermetyzacji
wywoa metod. Zgadza si, dziki hermetyzacji wywoa metod moemy
wykrystalizowa pewne fragmenty oblicze tak, e obiekt wywoujcy obliczenia nie musi
si martwi, w jaki sposb je wykona; po prostu wykorzystuje nasz metod. Z takimi
hermetyzowanymi wywoaniami metod moemy rwnie dokonywa wielu zadziwiajco
sprytnych operacji, takich jak na przykad zapisywanie ich do dziennikw czy te ponowne
wykorzystywanie w celu zaimplementowania mechanizmu Cofnij (ang. Undo) w naszej aplikacji.

Poprosz
z
ada si
enie sk
w
Zamwi wybranych enia.
pozycji iecie zamwi
oraz z
nk
wienia
e na bla
u zam y zapisan
iet
nk
sta
bla
zo
ktre
menu,
utwrz
Zamwi
enie()

z serem
zapiekank sodowy.
i napj

rem
z se
owy
sod

a
kank

ie
Zap
j
Nap

, czego

ju
Klient wie

chce,
ie.
zamwien
i skada

pobierzZam

wienie()
si
klienta i kiedy ju
Zamwienie od
Metoda ta
Kelnerka przyjmuje metod realizujZamwienie().
uje
przez klienta.
z tym upora, wywo
wienia zoonego
s realizacji Zam
rozpoczyna proce

12

pro

du

kt

(),
apiekank
przygotujZ apj()
przygotujN

cow

r
Burge lt
Ma

ko

duj
znaj
ieniu kcje
amw stru y
Na Z szelkie in tego, ab y
si w dne do waciw eruje
b
niez towa ienie ki ujc
ug
go
w
przy k. Zam rza, pos k
ja
e
posi Kucha takimi, ).
i
prac etodam iekank(
si m gotujZap
przy

re

ali

zu

jZa

ien

ie(

cje
Kucharz realizuje instruk
i
podane w Zamwieniu
edni
przygotowuje odpowi
posiek.

Automatyka w domu i zagrodzie

218

Mamy now zabawk! Sprawdzamy, jak dziaa SuperPilot

219

Co zawiera otrzymany dysk CD-R

220

A w midzyczasie w naszym barze szybkiej obsugi

223

Przyjrzyjmy si nieco dokadniej wzajemnym interakcjom

224

Zadania i zakresy odpowiedzialnoci

225

Od Baru do wzorca Polecenie

227

Nasze pierwsze POLECENIE

229

Denicja wzorca Polecenie

232

Wzorzec Command i SuperPilot

234

Implementujemy SuperPilota

236

Sprawdzamy moliwoci naszego SuperPilota

238

Nadszed wreszcie czas, aby utworzy troch dokumentacji

241

Implementacja mechanizmu wycofywania przy uyciu stanw

246

Kady pilot powinien posiada tryb Impreza!

250

Zastosowanie makropolece

251

Kolejne zastosowania wzorca Polecenie kolejkowanie da

254

Kolejne zastosowania wzorca Polecenie dania rejestracji

255

Twoja skrzynka narzdziowa

256

Rozwizania wicze

258

Wzorce Adapter oraz Fasada


Zdolno do adaptacji
W niniejszym rozdziale mamy zamiar dokona paru niesamowitych
wyczynw z dziedziny rzeczy niemoliwych, takich jak na przykad
woenie kwadratowego koka do okrgego otworu. Brzmi nierealnie? Nie
wtedy, kiedy mamy pod rk odpowiednie wzorce projektowe. Pamitasz wzorzec Dekorator? Podczas
pracy z nim owijalimy obiekty innymi obiektami tak, aby nada im nowe zachowania. Teraz mamy zamiar
postpowa tak samo, ale w nieco innym celu: chcemy sprawi, by ich interfejsy wyglday jak co, czym
nie s. Dlaczego jednak mielibymy to robi? Na przykad po to, aby zaadaptowa projekt oczekujcy
danego interfejsu do klasy, ktra implementuje zupenie inny interfejs. To jeszcze nie wszystko; skoro
ju jestemy przy tym temacie, przyjrzymy si rwnie innemu wzorcowi, ktry owija obiekty w celu
uproszczenia ich interfejsw.

Europejski standard ciennego


gniazda elektrycznego

Adaptery s wrd nas

Adapter

Standardowa wtyczka zasilajca

260

Adaptery zorientowane obiektowo

261

Wzorzec Adapter bez tajemnic

265

Denicja wzorca Adapter

267

Adaptery obiektw i klas

268

Temat dzisiejszej wieczornej pogawdki: Adapter obiektw i Adapter klas

271

Adaptery w wiecie rzeczywistym

272

Adaptujemy interfejs Enumeration do wymaga interfejsu Iterator

273

Temat dzisiejszej wieczornej pogawdki: wzorce Dekorator i Adapter

276

Nie ma to jak kino domowe

279

wiata, kamera, fasada!

282

Konstruujemy fasad naszego systemu kina domowego

285

Denicja wzorca Fasada

288

Regua ograniczania interakcji

289

Twoja skrzynka narzdziowa

294

Rozwizania wicze

296

Klient

danie
()

Klient jest zaprojektowany


niezgodnie z wymogami
interfejsu docelowego.

wy
celo

do
rfejs
inte

an

m
ieTu

()
one
acz

Adapter

Obiekt
adaptowany

interfejs
obiektu
adaptowa
nego

Adapter implementuje interfejs


docelowy i przechowuje
anego.
instancj obiektu adaptow

Indyk to interfejs
adaptowanego.

mentuje

imple
dapter
IndykA Kaczka.
y
docelow

obiektu

s
interfej

13

Wzorzec Metoda Szablonowa

Hermetyzacja algorytmw
Jestemy jak w transie: hermetyzowalimy ju proces tworzenia
obiektw, wywoania metod, zoone interfejsy, kaczki, indyki,
pizze ciekawe, co bdzie nastpne? Ot, teraz mamy zamiar zaj si
hermetyzacj fragmentw algorytmw, tak aby klasy podrzdne mogy podczepia si w rnych
miejscach wykonywanych oblicze. Co wicej, zajmiemy si rwnie regu projektowania, ktrej korzenie
wywodz si w prostej linii z Hollywood.

Zauwaylimy, e dwie
receptury s bardzo do siebie
podobne, chocia niektre
ich etapy wymagaj rnych
implementacji. Dziki temu
spostrzeeniu moglimy
uoglni receptur i umieci j
w klasie bazowej.

Herbata

2
3

Napoje
zawierajce
kofein

uoglnienie

He
Podklasa

rbata

niektre etapy
delegowane s do
klasy podrzdneja

W torebk herbaty do

Dodaj cytryn.

14

Zagrzej odpowiedni ilo wody.

Zaparz napj.

Nalej uzyskany napj do filianki.

Domieszaj do napoju odpowiednie


dodatki.

wrztku.

fein doskonale zna


Klasa NapjZKo
y receptury, cho
poszczeglne etap
etap pierwszy
sama wykonuje tylko
c realizacj
wiaj
zosta
i,
i trzec
i czwartego
iego
drug
etapw
ata.
Herb
i
a
klasom Kaw

Kawa

Zagrzej
odpowied
ni ilo
wody.
Zalej wrz
tkiem od
mierzon
porcj ka
Nalej kawy
wy.
do filiank
i.
Dodaj cu
kier i ml
eko do sm
aku.

y.
edni ilo wod
Zagrzej odpowi
wrztku.
bk herbaty do
2 W tore
i.
baty do filiank
3 Nalej her
do smaku.

ryn
cyt
aj
4 Dod

uoglnienie

niektre etapy
delegowane s do
klasy podrzdneja

Podklas
a Kawa

2
4

zon porcj
Zaparz odmier
kawy.
mleko.
Dodaj cukier i

Tworzymy klasy reprezentujce kaw i herbat (w jzyku Java)

299

Kawa i herbata, czyli klasy abstrakcyjne

302

Cigniemy nasz projekt o krok dalej

303

Wydobywanie metody recepturaParzenia()

304

Czego ju dokonalimy?

307

Spotkanie z wzorcem Metoda Szablonowa

308

Zrbmy sobie herbat

309

Co nam daje zastosowanie metody szablonowej?

310

Denicja wzorca Metoda Szablonowa

311

Bliskie spotkania z kodem aplikacji

312

Haczyk na wzorzec Metoda Szablonowa

314

Zastosowanie haczyka

315

Testujemy nasz aplikacj

316

Regua Hollywood

318

Regua Hollywood a wzorzec Metoda Szablonowa

319

Wzorzec Metoda Szablonowa w gbokiej kniei

321

Sortowanie przy uyciu wzorca Metoda Szablonowa

322

A teraz musimy posortowa troch kaczek

323

Porwnywanie kaczek z innymi kaczkami

324

Robimy maszyn do sortowania kaczek

326

Zabawy z ramkami

328

Aplety Java

329

Temat dzisiejszej wieczornej pogawdki:


wzorce Metoda Szablonowa oraz Strategia

330

Twoja skrzynka narzdziowa

332

Rozwizania wicze

333

Wzorce Iterator i Kompozyt

Zarzdzanie kolekcjami
Jest wiele sposobw grupowania obiektw w kolekcje. Mona
utworzy obiekty Array, Stack, List, Hashtable. Kady z nich ma swoje zalety i wady. Jednak w pewnym
momencie klient rozpocznie iteracyjne przetwarzanie elementw kolekcji. Czy wtedy ujawnisz mu swoj
implementacj? Mam nadziej, e nie. To nie byoby profesjonalne. Nie musisz si jednak obawia,
Twoja kariera zawodowa nie jest zagroona. W tym rozdziale przedstawimy metod, ktra umoliwia
klientom przetwarzanie iteracyjne bez wiedzy o tym, jak obiekty s przechowywane. Przedstawimy te
technik tworzenia superkolekcji (ang. super collections) obiektw, ktre pozwalaj na obsug bardzo
rozbudowanych struktur danych. Bdziemy te pisa o odpowiedzialnoci obiektw.

To jest kolekcja ArrayList,


ktra przechowuje menu
poszczeglnych restauracji.

Pa

nc

ake

en u

Wszystkie menu
House M

Din

erMenu

UJ

acka Menu

Menu restauracji U Jacka

Menu restauracji PancakeHouse


Menu restauracji Diner
tablica
Po z
ycjaMenu

Po z
ycjaMenu

Po z
ycjaMenu

Po z
ycjaMenu

klucz

klucz

Po z
ycjaMenu
klucz

2
Po z
ycjaMenu

ArrayList

Menu deserw

klucz

Po z
ycjaMenu

Po z
ycjaMenu

Po z
ycjaMenu

Hashtable

Po z
ycjaMenu

Po z
ycjaMenu

4
Po z
ycjaMenu

Po z
ycjaMenu

3
Po z
ycjaMenu

Po z
ycjaMenu

Kolekcja DinerMenu ma przechowywa podmenu.


Jednak nie moemy wprowadzi menu jako elementu
tablicy ze wzgldu na niezgodno typw.

Fuzja restauracji Diner i Pancake House

336

Implementacje menu ukasza i Miosza

338

Czy mona hermetyzowa iteracje?

343

Wzorzec Iterator

345

Wizanie iteratora z obiektem menu

347

Co ju mamy Szersze spojrzenie na kod naszego projektu

351

Uproszczenia po wprowadzeniu interfejsu java.util.Iterator

353

Jaki jest efekt kocowy?

355

Denicja wzorca Iterator

356

Jeden zakres odpowiedzialnoci

359

Iteratory i kolekcje

368

Iteratory i kolekcje w jzyku Java 5

369

I gdy ju miao by tak dobrze

373

Denicja wzorca Kompozyt

376

Projektujemy menu oparte na wzorcu Kompozyt

379

Implementacja klasy Menu

382

Powracamy do iteratora

388

IteratorPusty

392

Wzorce Iterator i Kompozyt razem

394

Twoja skrzynka narzdziowa

399

Rozwizania wicze

400

15

10

Wzorzec Stan
Stan obiektu
Mao znany fakt: wzorce Strategy i State to bliniaki, rozdzielone
zaraz po narodzinach. Jak ju wiemy, wzorzec Strategy umoliwi przeprowadzenie wielu
niezwykle udanych przedsiwzi opartych na zamiennie stosowanych algorytmach. Wzorzec State ma
inn rol. Jest ni wspomaganie obiektw w kontrolowaniu ich wasnych zachowa poprzez wewntrzn
zmian stanu. atwo usysze, jak mwi swoim podopiecznym: Powtarzaj za mn: jestem wystarczajco
zdolny, jestem wystarczajco dobry, dam rad to zrobi.
Krtka narada

405

Maszyny stanowe 101

406

Piszemy kod

408

Wiedziae, e to jest blisko zmiana!

412

Kopotliwy STAN rzeczy

414

Deniowanie interfejsw i klas reprezentacji stanu

417

Implementowanie klas Stan

419

Nowa wersja automatu sprzedajcego

420

Denicja wzorca Stan

428

Wzorzec Stan kontra wzorzec Strategia

429

Wzorzec Stan, werykacja projektu

435

Niemal zapomnielimy!

438

Twoja skrzynka narzdziowa

441

Rozwizania wicze

442

gdzie automatyczny sprzedawca


nigdy nie jest w poowie pusty

J e st
a
monet

lic

16

aGum

zb

=0

aG

ze

kr

an

ni e m on
a
N ie m
y
monet

li c z b

pr

et y

w k ad an

ie m on et

Brak
gum

um

>

zw ra ca

Automaty Sprzedajce SA

autom atu
konce pcj pracy kontr olera
nie
Poni ej przed staw iamy nasz
y nadz iej, e zaimp lemen towa
Mam
.
ucia
do
gum
ego
sprze dajc
przys zoc i
spraw i Wam trudn oci. W
kt
proje
tego schem atu w Javie nie
o
my
nowe zacho wani a, wic prosi
bdz iemy zape wne doda wa
mody fikow ania.
do
y
atw
i
yczny
elast
moli wie
maty Sprz edaj ce
Inyn ierow ie firmy Auto

a n ie
w yd a w
g um y

Guma na
da
sp r z e

ie

ga

ki

11

Wzorzec Proxy
Kontrola dostpu do obiektu
Prbowae kiedy stosowa metod dobrego i zego?

Ty jeste tym

dobrym, ktry zrobi wszystko, o co si go poprosi, ktry jest zawsze miy i uprzejmy. Nie chcesz jednak,
eby kady mg prosi o Twoje usugi. To jest miejsce dla zego, ktry bdzie kontrolowa dostp do
Ciebie. Takie jest wanie zadanie porednikw (ang. proxy) w modelu obiektowym kontrolowanie
i zarzdzanie dostpem. Jak si przekonamy, istnieje bardzo wiele schematw takiego porednictwa.
Obiekty Proxy mog przekazywa wywoywanie metody obiektowi w innym wle internetu; bywa te,
e zastpuj wyjtkowo leniwe obiekty.

Brzydk

adny

Kontrolowania stanu automatw sprzedajcych

448

Rola zdalnego porednika

452

RMI wycieczka z przewodnikiem

455

Zdalny porednik automatu sprzedajcego

468

Porednik zdalny, za kulisami

476

Denicja wzorca Proxy

478

Porednik wirtualny

480

Projektowanie wirtualnego porednika do wywietlania okadek

482

Porednik wirtualny, za kulisami

488

Wykorzystanie mechanizmw Java API

492

Teatrzyk ochrona przedmiotw

496

Budowanie dynamicznego porednika

497

ZOO porednikw

506

Twoja skrzynka narzdziowa

508

Rozwizania wicze

509

<<interface>>
Przedmiot

<<interface>>
InvocationHandler

danie()

invoke()

skadaj si
Na porednika
dwie klasy.
PrawdziwyPrzedmiot
danie()

Proxy
danie()

teraz

InvocationHandler
invoke()

17

12

Wzorce zoone
czenie wzorcw
Przyszoby Ci do gowy, e wzorce mog pracowa razem? Bylimy ju
wiadkami wielu niespokojnych Pogawdek przy kominku (a omin Ci Death Match wzorcw, ktry
wydawca kaza wyrzuci*) czy wsuchujc si w ich ton mona jeszcze liczy na to, e wzorce bd ze
sob wsppracowa? Moesz wierzy lub nie, ale najbardziej wyszukane projekty obiektowe wykorzystuj
wiele wzorcw jednoczenie. Przygotuj si na kolejny poziom wiedzy o wzorcach projektowych. Czas na
wzorce zoone.

Beat jest ustawiony na 119 BPM i chcemy


zwikszy szybko do 120 BPM.

Klikamy przycisk
zwikszajcy
szybko

Widok

co powoduje wywoanie
kontrolera.

Kontroler da od modelu
zwikszenia wartoci
BPM o jeden.

Controler
Pasek beatu
pulsuje co p
sekundy.

Widok

Poniewa szybko beatu to 120


BPM,
widok jest uaktualniany co p sekundy.

tM
Bea odel
start()

ustawBPM()stop()
zBPM()
pobier
Widok zostaje
uaktualniony, aby
wywietla 120 BPM.

18

zmianie BPM.
Widok jest powiadamiany o
BPM().
Wywouje metod modelu pobierz

Wzorzec zoony

518

Powrt kaczek

519

Potrzebujemy adaptera gsi

522

Wprowadzamy zliczanie kwakni

524

Fabryka produkujca kaczki

526

Tworzymy stado kaczek

531

Przygotowanie interfejsu Observable

534

Co zrobilimy?

541

Widok z lotu kaczki diagram klas

542

Model-Widok-Kontroler piosenka

544

Kluczem do schematu MVC bd wzorce projektowe

546

Spojrzenie na schemat Model-Widok-Kontroler przez pryzmat wzorcw

550

Wykorzystujemy MVC do sterowania beatem...

552

Piszemy kod elementw

555

Widok

557

A teraz kontroler

560

Eksplorujemy moliwoci wzorca Strategia

563

Adaptowanie modelu

564

Nowy kontroler SerceKontroler

565

Wzorzec MVC i sie WWW

567

Model 2 a wzorce projektowe

575

Twoja skrzynka narzdziowa

578

Rozwizania wicze

579

13

Nowe ycie z wzorcami


Wzorce projektowe w praktyce
Ach, jeste ju gotowy na spotkanie z nowym wspaniaym wiatem
penym wzorcw projektowych Ale zanim rozpoczniesz wdrwk ku nowym
horyzontom, powi chwil na przeczytanie rozdziau powiconego pewnym szczeglnym kwestiom,
ktre pojawiaj si, gdy rozpoczynasz stosowanie wzorcw w codziennej pracy. Nie wszdzie jest tak
piknie, jak w Obiektowie. Przygotowalimy wic may przewodnik, ktry pomoe Ci odnale si
w twardej rzeczywistoci

Przewodnik na nowe ycie z wzorcami

na nowe
Przewodnik
ami
rc
ycie z wzo

ir porad,
podrczny zb towymi
osz, nasz
mi projek
ca
Przy jmij, pr
or
wz
z

Ci y
ktre pomog acy i zmaganiach.
pr
w codziennej

jektowy;
wi o:
wzorzec pro
my w nim m
z terminem
Bdzie
mog Ci si
zwizanych
, jak bardzo
ozumieniach
ych i o tym
tow
niepor
jek
pro
w
gach wzorc
rzebne;
katalo
nie jest to pot
przyda;
tam, gdzie
a wzorcw
iu stosowani
w;
orc
wz
unikan
to zajcie
niu
wa
, e nie jest
ym klasyfiko
ych i o tym
orem
waciw
jak zosta aut
w projektow
waniu wzorc branych. Dowiesz si,
definio
wy
dla
ane
zarezerwow
jak
,
ag
n pow
wzorcw;
ktujemy z rw
u, ktre tra
niach umys
of Four.
wicze
iczego Gang
Zen.
ch tajemn
mistrzowie
ere
w
Czt
wnik wzorc
o Gangu
kady uytko
imy tosam
inien mie
Ujawn
pow
ki
ksi
imy, jakie
stosujc
,
tw
mis
Zdradz ych.
na progra
i wpywa
projektow
ych.
by przyjaci
iemy, jak zdo gi wzorcw projektow
Opow
terminolo
precyzyjn

ard
Richlm
He

578

Denicja wzorca projektowego

597

Drugie spojrzenie na denicj wzorca

599

Niech moc bdzie z Tob

600

Katalog wzorcw

601

Jak tworzy wzorce

604

Zosta autorem wzorcw projektowych

605

Porzdkowanie wzorcw projektowych

607

Mylenie wzorcami

612

Gowa pena wzorcw

615

Nie zapominaj o potdze jednolitego sownictwa

617

Pi podstawowych sposobw promowania Twojego sownictwa

618

Gang Czterech w Obiektowie

619

Podr dopiero si zaczyna

620

Inne rda informacji o wzorcach

621

ZOO pene wzorcw

622

Walka ze zem przy uyciu antywzorcw

624

Twoja skrzynka narzdziowa

626

Opuszczamy Obiektowo

627

Ralph Johnson

Gang czterech
John
Vlissides

Erich Gamma

19

14

Dodatek inne wzorce


Nie wszyscy mog by sawni. Przez ostatnie dziesi lat wiele si w wiecie
wzorcw zmienio. Od czasu pierwszego wydania ksiki Design Patterns: Elements of Reusable
Object-Oriented Software (Wzorce projektowe) programici wykorzystali opisane w nich schematy
tysice razy. Wzorce, ktre zebralimy w tym dodatku, to dopracowane, kompletne, oficjalne
wzorce grupy GoF. Rni si od wczeniej opisanych tylko tym, e nie spotkamy ich tak czsto, jak
tych, ktrym powicilimy cae rozdziay. Nie umniejsza to ich zalet i nie powinno zniechca do ich
stosowania tam, gdzie wymaga tego sytuacja. Celem niniejszego dodatku jest zapewnienie Ci szerszej
orientacji w najatwiej dostpnych zasobach zgromadzonej przez lata wiedzy.
Bridge (most)

Klient da, aby Go


ci
o
pobra informacje ze
ar t
ikW
struktury Compoztu
n

ska
Dodawanie nowych metod
zW j()
klasy Go nie wpywa na obier otne rie()
()
p ow alo ()
any
r
kompozyt.
Zd bierzK iaka wod
o
B
l
z
o
p bier
g
po bierzW
po

wo wywoania
Klasa Go musi mie moli
j z klas. Jest
metody pobierzStan() kade
wadzi nowe metody,
miejscem, gdzie mona wpro
y.
klient
z ktrych bd korzysta

632
634

Flyweight (waga pirkowa)

636

Interpreter (interpreter)

638

Mediator (mediator)

640

Memento (memento)

642

Prototype (prototyp)

644

Visitor (go)

646

pobierzStan()
pob
ierzS
tan(
)
po
bie
rzS
Pozycja
tan
Menu
()

()
tan
rzS
bie
po

Klient i Obiekt
przechodzenia

erser)
Obiekt przechodzenia (Trav
przez ca
umie przeprowadzi gocia
struktur kompozytow.

S
20

Builder (budowniczy)
Chain of Responsibility (acuch odpowiedzialnoci)

Stan()
pobierz

Go

Skadnik

Skorowidz

630

Jedyne, czego wymagamy od


klas kompozytu, to metody
pobierzStan() (i tego, eby nie
obawiay si ujawnienia).

Menu

Pozycja
Menu

Skadnik

649

Rozdzia 3. Wzorzec Dekorator

Dekorowanie
zachowania obiektw
Zawsze sdziem, e
prawdziwi mczyni tworz podklasy
dla wszystkiego, co si tylko do tego
nadaje. Tak byo do czasu, gdy
dowiedziaem si o korzyciach, jakie
daje moliwo rozszerzania moliwoci
aplikacji na poziomie dziaania, a nie
kompilacji. A teraz spjrzcie
tylko n a mnie!

W zasadzie niniejszy rozdzia moemy rwnie dobrze zatytuowa


Otwieranie oczu programistom z nadmiernymi skonnociami do
naduywania dziedziczenia. W tym rozdziale sprbujemy krytycznie przyjrze si
zwyczajowym skonnociom do naduywania mechanizmu dziedziczenia oraz nauczymy Ci sposobw
dekorowania zachowania klas w czasie dziaania programu przy uyciu pewnej formy kompozycji obiektw.
Dlaczego? Po zapoznaniu si z technikami dekoracji zachowania klas bdziesz mg wyposaa swoje
(i nie tylko) obiekty w nowe moliwoci bez koniecznoci dokonywania jakichkolwiek modyfikacji
w kodzie klas podstawowych.

to jest nowy rozdzia

109

Historia pewnej kafejki

Witamy w Star Caf


Star Caf jest jedn z najszybciej rozwijajcych si sieci
kawiarni*. Jeeli przez okno widzisz jedn z nich, moesz
by cakowicie pewny, e gdy wyjrzysz za rg najbliszego
skrzyowania, zobaczysz kolejn.
Poniewa rozwijaj si tak szybko, ostatnio niemal
rozpaczliwie walcz z tym, aby kolejne aktualizacje ich systemu zamwie
naday za cigle rozszerzajc si palet oferowanych napojw.
Kiedy pierwsza kawiarenka Star Caf otwara swe podwoje dla klientw,
diagram klas ich systemu zamwie wyglda mniej wicej tak:

akcyjna, ktrej
Napoje to klasa abstr
jw
zeglne rodzaje napo
podklasami s poszc
j kafejce.
oferowanych w nasze

w kadej
Zmienna obiektowa opis jest ustawiana
h
lnyc
czeg
posz
opisy
uje
podklasie; przechow
y
palon
o
mocn
ty,
komi
Zna
np.
jak
jw,
napo
gatunek kawy!.

Napj
opis

Metoda koszt() jest abstrakcyjna;


poszczeglne podklasy
powinny posiada wasne jej
implementacje.

StarCafeSpecial
koszt()

pobierzOpis()
koszt()
// Inne uyteczne
metody...

MocnoPalona
koszt()

ca
Metoda pobierzOpis() jako rezultat zwra
warto zmiennej opis.

Bezkofeinowa
koszt()

Espresso
koszt()

Kada podklasa posiada zaimplementowan metod koszt(), ktra zwraca cen danego napoju.

* Oczywicie, jest to sie kcyjna, wszelkie podobiestwo do jakiejkolwiek rzeczywistej instytucji


jest cakowicie przypadkowe i niezamierzone przyp. tum.

110

Rozdzia 3

Wzorzec Dekorator

Do kadej kawy moesz rwnie zamwi szereg dodatkw, takich jak mleko,
mleczko sojowe, mocha* (znana rwnie pod nazw czekolada). Moesz pokry
to wszystko bit mietan. Star Caf za kady z tych dodatkw dolicza niewielk
opat, wic, chcc nie chcc, waciciele sieci musieli informacje o dodatkach (i ich
moliwych kombinacjach) wbudowa w swj system zamwie.
Ich pierwsza prba wygldaa mniej wicej tak
Napj
opis
pobierzOpis()
koszt()
// Inne uyteczne metody...

Bezkofeinowa
ZCzekolad

MocnoPalona
NapojeMocnoPalonaZMlekiem

koszt()

koszt()

koszt()

MocnoPalonaZCzekolad

koszt()

MocnoPalonaZMlekiemCzekoladMl
koszt()
eczkiemSojowym
koszt()

koszt()

cost()
BezkofeinowaZMlekiem

koszt()
BezkofeinowaZMlec

koszt()

StarCafeSpecialZMlekiemCzekoladEspr
Espresso
essoWithSteamedMilk
koszt()

cost()
EspressoZMlekiem
DarkRoastWithSoy
cost()
BezkofeinowaZMlekiem
koszt()
StarCafeSpecialZBitmietan
DarkRoastWithSoy
NapojeBezkofeinowaZBitmietan
koszt()
DecafWithSoyCzekoladMleczkiemSojowym
koszt()
MleczkiemSojowym
MocnoPalonaZBitmietan
cost()
BezkofeinowaZCzekoladNapoje
cost()
CzekoladMleczkiemSojowym
koszt()
koszt()

cost()
MocnoPalonaZCzekolad
MleczkiemSojowym

koszt()

EspressoZMlekiemCzekolad

BezkofeinowaZCzekolad
MleczkiemSojowym

koszt()

EspressoZBitmietanEspressoWith

StarCafeSpecial
koszt()

koszt()
MocnoPalonaZCzekolad

koszt() MocnoPalonaZBitmietan

koszt()

koszt()

Bezkofeinowa

StarCafeSpecialZCzekolad
MleczkiemSojowym

koszt()

Bezkofeinowa
koszt()
ZMlekiemCzekolad

BezkofeinowaZMlekiemCzekolad
NapojeMocnoPalonaZBitmietan
MleczkiemSojowym

koszt()

StarCafeSpecialZMlekiemCzekolad
MleczkiemSojowym

StarCafeSpecial
ZCzekolad

MocnoPalonaZBitmietan
CzekoladMleczkiemSojowym
koszt()

koszt()

koszt()

MocnoPalonaZMlekiemCzekolad

koszt()

StarCafeSpecialZMlekiem
Czekolad

StarCafeSpecial
ZMlekiem

BezkofeinowaZBitmietan

BezkofeinowaZBitmietanNapoje
koszt()
koszt()

koszt()
EspressoZMlekiemCzekolad
MleczkiemSojowym
BezkofeinowaZCzekoladMleczkiem
StarCafeSpecialZCzekolad
cost()
Sojowym
EspressoZCzekoladMleczkiem
MleczkiemSojowym
StarCafeSpecialZMlekiemCzekolad
Sojowym
cost()
BezkofeinowaZMlekiem
cost()
MleczkiemSojowym
MleczkiemSojowym
koszt()
koszt()

koszt()

Uuuaaa!
To si dopiero
nazywa eksplozja
klas!

koszt()

koszt() obliczaj
Poszczeglne metody
zy uwzgldnieniu
cen danego napoju pr
z wszystkich
ora
odpowiedniej kawy
w.
tk
da
do
h
zamwionyc

* Pod nazw Mocha (lub Arabica Mocha) kryje si rwnie znakomity gatunek kawy arabskiej,
odznaczajcy si wybitnie czekoladowym aromatem i redni moc napoju; polecam! przyp. tum.

jeste tutaj

111

Pogwacenie regu projektowania

Wysil szare
komrki
Chyba dla wszystkich jest oczywiste, e projektanci ze Star Caf sami sobie narobili kopotw,
tworzc struktur aplikacji, ktra z punktu widzenia serwisowania, modyfikacji i rozbudowy jest po
prostu koszmarnym snem szalonego programisty. Wyobra sobie tylko, co oni powinni zrobi, jeli
cena mleka pjdzie w gr? Albo co maj zrobi, jeli firma wprowadzi now polew karmelow?
Sprbuj pomyle nieco szerzej, nie tylko o problemie serwisowania aplikacji ktre spord
omawianych do tej pory regu projektowania zostay pogwacone podczas tworzenia tego projektu?
Wskazwka: dwie z tych regu zostay tutaj kompletnie podeptane!
Przecie to gupie po co nam
te wszystkie klasy? Czy nie moemy
po prostu uy zmiennych obiektowych
oraz mechanizmu dziedziczenia z klasy
nadrzdnej do obsugi wszystkich
dodatkw?

No dobrze, zatem sprbujmy tak zrobi. Projektowanie rozpoczniemy z naszej


superklasy bazowej Napj, do ktrej dodamy zmienne obiektowe odpowiadajce
temu, czy dany napj bdzie z mlekiem, czy te nie; czy bdzie z czekolad,
czy nie itd.
Napj
opis
mleko
mleczko sojowe
czekolada
bita mietana
pobierzOpis()
koszt()
zMlekiem()
dodajMleko()
zMleczkiemSojowym()
dodajMleczkoSojowe()
zCzekolad()
dodajCzekolad()
zBitmietan()
dodajBitmietan()
// Inne uyteczne metody...

112

Rozdzia 3

typu boolean dla kadego


z dodatkw.
Teraz zaimplementujemy metod koszt() bezporednio w klasie Napj (do
tej pory bya to metoda abstrakcyjna), tak e bdzie moga policzy cen
powizan z dodatkami dla danego obiektu klasy Napj. Klasy podrzdne
bd nadal miay wasne wersje metody koszt() (czyli bd przesaniay
metod koszt()), aczkolwiek bd rwnie wywoyway t metod
bezporednio z klasy nadrzdnej (czyli superwersj tej metody) tak,
aby mogy policzy cen napoju podstawowego plus koszty wszystkich
zamwionych do niego dodatkw.

oraz ustawiaj
Te metody pobieraj
logicznych dla
ch
ny
wartoci zmien
tkw.
poszczeglnych doda

Wzorzec Dekorator
Napj

A teraz dodajmy do naszego diagramu


poszczeglne podklasy, po jednej dla
kadego napoju wyszczeglnionego
w menu:

opis
mleko
mleczko sojowe
czekolada
bita mietana

sie
plementowana w kla
Metoda koszt() zaim
szt
ko
ty
wi
ko
ca
wyliczaa
nadrzdnej bdzie
ju dodatkw,
po
na
go
ne
da
do
h
onyc
wszystkich zamwi
() w klasach
niajce metody koszt
sa
ze
pr
y
gd
s
za
dc
po
, pozwalajc
o
aln
jon
kc
erz jej fun
podrzdnych rozsz
wego.
go napoju podstawo
doczy cen dane

pobierzOpis()
koszt()
zMlekiem()
dodajMleko()
zMleczkiemSojowym()
dodajMleczkoSojowe()
zCzekolad()
dodajCzekolad()
zBitmietan()
dodajBitmietan()

napoju
() musi policzy cen
Kada metoda koszt
datkw,
do
n
ce
stpnie doda
podstawowego, a na
sy
kla
z
()
szt
ko
lu metod
wywoujc w tym ce
nadrzdnej.

// Inne uyteczne metody...

MocnoPalona

StarCafeSpecial

Bezkofeinowa

koszt()

koszt()

koszt()

Espresso
koszt()

Zaostrz owek
Sprbuj napisa kod implementujcy metod koszt() dla nastpujcych klas
(moesz uy w zapisie pseudokodu Java):
public class Napj {

public class MocnoPalona extends Napj {

public double koszt() {

public MocnoPalona() {
opis = "Znakomity, mocno palony gatunek
kawy!"
}
public double koszt() {

}
}

}
}

jeste tutaj

113

Wpyw zmian

Zobaczmy,
w sumie wyszo z tego pi
klas. Czyli definitywnie jest to
kierunek, w ktrym powinnimy si
dalej porusza.
Nie jestem tego taki
pewny; jeeli sobie pomyl,
jakie zmiany moe przechodzi ten
projekt w przyszoci, przewiduj
kilka potencjalnych problemw.

Zaostrz owek
Jakie wymagania (bd inne czynniki) mog si zmienia tak, e bd miay wpyw na nasz projekt?
Zmiana cen poszczeglnych dodatkw bdzie nas zmuszaa do modyfikacji istniejcego kodu.
Wprowadzanie do oferty nowych dodatkw bdzie nas zmuszao do dodawania nowych metod oraz modyfikacji kodu metody koszt()
w klasie nadrzdnej.
Moe si okaza, e w ofercie pojawi si nowe napoje. Dla niektrych napojw (na przykad dla mroonej herbaty) pewne dodatki
mog by nieodpowiednie, aczkolwiek mimo wszystko podklasa Herbata powinna dziedziczy takie metody, jak np. zBitmietan().
A co w sytuacji, kiedy klient zayczy sobie podwjn porcj czekolady?

ko
Twoja

114

lej:

Rozdzia 3

przeko
Jak ju i
s
n a li m y le 1 .,
ia
z
w rozd d
aw
to napr obry
d
nie jest
!

s
pomy

Wzorzec Dekorator

Mistrz i ucze
Mistrz: Od naszego ostatniego spotkania upyno ju cakiem
sporo czasu, mody czowieku Czy spdzae duo czasu
pogrony gboko w rozwaaniach nad istot dziedziczenia?
Ucze: Tak, Mistrzu. Dziedziczenie jest zaiste potn broni,
nauczyem si jednak, e nie zawsze jej uycie prowadzi do wystarczajco
elastycznych i atwych w modyfikacji projektw.
Mistrz: O, co za niespodzianka! Poczynie, widz, pewne postpy! A zatem
powiedz mi, mj mody adepcie, w jaki sposb moemy uzyska kod,
ktrego da si uywa wielokrotnie, inaczej ni poprzez dziedziczenie?
Ucze: Mistrzu, nauczyem si, e istniej sposoby, ktre podczas dziaania
programu daj takie same efekty, jakie normalnie daje dziedziczenie;
naley zatem skorzysta z odpowiedniej kompozycji i delegacji.
Mistrz: Prosz, kontynuuj
Ucze: Kiedy dziedzicz dane zachowania poprzez tworzenie klasy podrzdnej,
takie zachowanie jest tworzone statycznie podczas kompilacji programu. Co wicej,
wszystkie klasy podrzdne musz dziedziczy te same zachowania. Jeeli jednak
mog rozszerzy zakres zachowa obiektu poprzez kompozycj, takiej operacji
mog dokona dynamicznie podczas dziaania programu.
Mistrz: Bardzo dobrze, mj mody adepcie, jeste ju bliski ujrzenia potgi i mocy
kompozycji.
Ucze: Tak, Mistrzu. Obecnie mog ju przy uyciu tej techniki dodawa nowe
zadania do poszczeglnych obiektw, wczajc w to zadania, o ktrych nawet
si nie nio projektantom klasy nadrzdnej. Co wicej, nie musz w aden sposb
modyfikowa ich kodu!
Mistrz: A czego nauczye si o wpywie, jaki zastosowanie kompozycji wywiera
na moliwo zarzdzania i modyfikacji kodu programu?
Ucze: To jest wanie to, do czego zmierzaem, Mistrzu. Wykorzystujc
dynamiczn kompozycj obiektw, mog im nadawa nowe cechy poprzez proste
tworzenie nowego kodu, a nie modyfikacj kodu istniejcego. Zatem, poniewa nie
bd modyfikowa istniejcego kodu, szanse na wprowadzenie nowego bdu czy
te zaistnienie nieoczekiwanych efektw ubocznych zdecydowanie malej.
Mistrz: Bardzo dobrze. Wystarczy na dzisiaj, mody czowieku. Teraz chciabym,
aby si oddali i odda dalszym medytacjom i rozwaaniom na ten temat
Pamitaj, kod powinien by tak zamknity (na zmiany), jak kwiat lotosu
o zmierzchu, ale jednoczenie tak otwarty (na rozbudow), jak kwiat lotosu o wicie.

jeste tutaj

115

Regua otwarte-zamknite

Regua otwarte-zamknite
Nasz mody adept sztuki projektowania jest teraz na najlepszej drodze do poznania
jednej z najwaniejszych regu projektowania:
Regua projektowania
Klasy powinny by otwarte
na rozbudow, ale zamknite
na modyfikacje.

OTWARTE

Wejd prosz, jest otwarte.


Moesz bez skrpowania
rozbudowywa nasze
klasy dowolnymi nowymi
zachowaniami. Jeeli Twoje
potrzeby lub wymagania
ulegn zmianie (a my wiemy, e wczeniej czy pniej
tak wanie si stanie), po prostu id do przodu
i dokonuj rozbudowy wedle wasnego uznania.

ZAMK NITE
GODZIN Y PR

ACY

PON. OD __
__ _DO __ __
_
W T. OD __
__ _ DO __ __
_
R . OD __
__ _ DO __ __
_
CZW. OD __
__ _ DO __ __
_
PI . OD __
__ _ DO __ __
_

Przepraszamy,
zamknite. To
prawda, spdzamy mas czasu, pracujc
nad tym, aby kod aplikacji by stabilny i wolny od
bdw, wic nie moemy pozwoli Ci go ot, tak
sobie modykowa. Kod musi, niestety, pozosta
zamknity na wszelkie modykacje. Jeeli Ci si to
nie podoba, moesz porozmawia z przeoonym.
Naszym celem jest umoliwienie atwej rozbudowy poszczeglnych
klas poprzez dodawanie im nowych zachowa, ale bez koniecznoci
modyfikacji ich istniejcego kodu. Co otrzymamy w zamian za nasze
wysiki po osigniciu tego celu? Struktury, ktre bd si atwo
adaptoway do zmian i bd wystarczajco elastyczne, aby przyj nowe
zachowania speniajce nowe wymagania.

116

Rozdzia 3

Wzorzec Dekorator

Nie ma niemdrych pyta

P:

P:

O:

O:

Otwarte na rozbudow
i zamknite na modyfikacje?
To wyglda na swego rodzaju
sprzeczno. W jaki sposb mona
osign tak struktur?
To jest bardzo dobre pytanie.
Faktycznie, na pierwszy rzut oka wyglda
to na sprzeczno. W kocu, jak by na to
nie patrze, im mniejsze s moliwoci
modyfikacji danego czego, tym trudniej
jest to co rozbudowa, prawda?
Jak si jednak okazuje, w programowaniu
zorientowanym obiektowo istnieje kilka
pomysowych technik pozwalajcych na
rozbudow istniejcych systemw nawet
w sytuacji, kiedy nie moemy modyfikowa
zasadniczego kodu aplikacji. Przypomnij
sobie wzorzec Obserwator (o ktrym
mwilimy w rozdziale 2.) Dodajc
nowe obiekty obserwujce, moemy
rozbudowa obiekt obserwowany bez
koniecznoci dodawania nowego kodu
do tego ostatniego. Niebawem poznasz
kilka nowych sposobw rozbudowy czy
te dodawania kolejnych zachowa przy
uyciu innych technik programowania
zorientowanego obiektowo.

P:

No dobrze, rozumiem
zasady funkcjonowania
wzorca Observer, ale w jaki
sposb, oglnie mwic, mona
zaprojektowa co, co bdzie
podatne na rozbudow, ale
jednoczenie zamknite na
modyfikacje?

O:

Wiele wzorcw projektowych


daje nam ju wielokrotnie sprawdzone
w praktyce rozwizania, ktre pozwalaj
na ochron kodu aplikacji przed modyfikacj przy jednoczesnej rozbudowie jej
funkcjonalnoci. W niniejszym rozdziale
znajdziesz dobry przykad zastosowania
wzorca Dekorator przy jednoczesnym
postpowaniu zgodnie z regu
otwarte-zamknite.

W jaki sposb mog


stworzy struktur (aplikacji),
w ktrej kady z elementw
bdzie zgodny z regu
otwarte-zamknite?
Zazwyczaj nie da si tego zrobi.
Tworzenie elastycznych i otwartych na
rozbudow aplikacji zorientowanych
obiektowo bez modyfikacji istniejcego
kodu wymaga powicenia dodatkowego
czasu i zasobw. Oglnie rzecz biorc,
zazwyczaj nie moemy sobie pozwoli na
takie zaprojektowanie kadego elementu
naszej aplikacji (co wicej, prawdopodobnie
byaby to zwyka strata czasu, a wic
i pienidzy). Projektowanie zgodnie
z regu otwarte-zamknite zazwyczaj
wymaga wprowadzenia nowych poziomw
abstrakcji, co nieuchronnie prowadzi do
powikszenia stopnia skomplikowania

kodu naszej aplikacji. Salomonowym


rozwizaniem jest wic koncentrowanie
si raczej na tych obszarach systemu,
dla ktrych prawdopodobiestwo
wystpienia znaczcych zmian
jest najwiksze, i stosowanie regu
projektowania wanie tam.

P:

Bd wiedzia, ktre
obszary zmian s najwaniejsze?

O:

Czciowo jest to kwestia


dowiadczenia w projektowaniu systemw
zorientowanych obiektowo, jak rwnie
oczywicie dogbna znajomo
dziedziny, dla ktrej dany system powstaje.
Szczegowa analiza innych przykadw
i rozwiza z pewnoci pomoe Ci
w procesie nauki identyfikacji obszarw
zmiennych, ktre bd wystpoway
w Twoich aplikacjach.

Pomimo, i moe to pozornie wyglda na


sprzeczno, istniej techniki programowania
zorientowanego obiektowo pozwalajce na
rozbudow funkcjonalnoci kodu bez koniecznoci
jego bezporedniej modyfikacji.
Wybierajc obszary kodu aplikacji, ktre powinny
zosta rozbudowane, powiniene zachowa
umiar i zdrowy rozsdek; postpowanie zgodnie
z regu otwarte-zamknite WSZDZIE jest
niepotrzebn strat czasu, zasobw, zazwyczaj
te pienidzy, a poza tym moe prowadzi do
powstania bardzo skomplikowanego i trudnego
do zrozumienia kodu programu.

jeste tutaj

117

Spotkanie z wzorcem Dekorator

Spotkanie z wzorcem Dekorator

OK, mam do tego klubu Mionikw


projektowania zorientowanego obiektowo.
Mamy tutaj powany, rzeczywisty problem!
Pamitacie o nas? Star Caf? Czy Wy naprawd
sdzicie, e ktra z tych Waszych regu
projektowania moe nam w czym pomc?

Jak si niedawno przekonalimy, prba odwzorowania systemu


zamwie napojw wraz z rnymi dodatkami przy uyciu
mechanizmw dziedziczenia nie daa zbyt dobrych rezultatw
wystpowaa eksplozja klas, otrzymywalimy sztywny projekt,
efektem byy te prby rozbudowy klasy bazowej mechanizmami
nieodpowiednimi dla niektrych klas podrzdnych.
Zamiast tego w chwili obecnej zrobimy co zupenie innego:
rozpoczniemy od przygotowania napoju podstawowego. Dodatkami
udekorujemy go dopiero podczas dziaania programu. Przykadowo,
jeeli klient zayczy sobie czarn, mocno palon kaw z czekolad
i bit mietan, bdziemy postpowa nastpujco:

We obiekt MocnoPalona.

1
2

Udekoruj go obiektem Czekolada.

Udekoruj go obiektem Bitamietana.

Wywoaj metod koszt() i przy uyciu


mechanizmu delegacji dodaj koszty dodatkw.

No dobrze, ale w jaki sposb mog dekorowa poszczeglne obiekty


i w jaki sposb zastosowa tutaj delegacj? Zobaczmy zatem, jak to
dziaa.

118

Rozdzia 3

Wzorzec Dekorator

Konstruowanie zamwienia przy uyciu Dekoratorw


1

a
cnoPalon
biekt Mo lasy Napj
o
e

j,
a
t
Pami
szt(),
ania z k
y zachow owan metod ko
t
dziedzicz
n
e
m
le
zaimp
i posiada a koszt napoju.
licz
y
w
ktra

Rozpoczynamy od naszego obiektu


MocnoPalona.
koszt()

M o c n o Pa l o na

Klient zayczy sobie czekolady, wic tworzymy


obiekt Czekolada i zawijamy go dookoa
obiektu MocnoPalona.

m. Jego typ
jest dekoratore
Obiekt Czekolada
wanego, czyli
ro
ko
p obiektu de
ty
a
dl
ie
rc
ie
zw
od
Napj (przez
dku obiektu klasy
taj, e po prostu
w naszym przypa
tu
a rozumiemy
dl
ie
rc
ie
w
dz
o
sowo
o typu).
jest tego sameg

a swoj metod
rwnie posiad u moemy
da
la
ko
ze
C
,
Jak wida
polimorfizm
wasnociom
Czekolad,
koszt() i dziki
rego dodamy
kt
do
j,
em
p
na
y
d
da jest podtyp
traktowa ka
iewa Czekola
on
(p
j
p
na
y
jako kolejn
.
klasy Napoje)

koszt()

koszt()

M o c n o Pa l o na

Czekolada
3

Klient yczy sobie rwnie bitej mietany, wic tworzymy oczywicie


dekorator Bitamietana i zawijamy go dookoa obiektu Czekolada.

koszt()

Bi

koszt()

koszt()

M o c n o Pa l

tam

Mocha

o na

Bitamietana jest dekoratorem, wic rwnie


odzwierciedla typ obiektu MocnoPalona i posiada
zaimplementowan metod kosz().

ietana

Czyli obiekt MocnoPalona zawinity w obiekty Czekolada i Bitamietana


jest nadal napojem (obiektem klasy Napoje), wic moemy z nim zrobi
dokadnie to samo, co z czystym obiektem MocnoPalona, wczajc
w to wywoywanie jego metody koszt().

jeste tutaj

119

Charakterystyki dekoratora

A teraz nadszed wreszcie czas na obliczenie kwoty, jak powinien zapaci klient za
swoje zamwienie. Dokonamy tego poprzez wywoanie metody koszt() najbardziej
zewntrznego dekoratora, Bitamietana, ktry z kolei bdzie delegowa obliczanie
kosztw do obiektw, ktre dekoruje. Po uzyskaniu wynikw ich oblicze dekorator ten
dodaje swj koszt (bitej mietany) i dziki temu otrzymujemy cakowity koszt napoju.

Po pierwsze, wywoujemy
ej
metod koszt() najbardzi
a, jakim
zewntrznego dekorator
jest Bitamietana.

1.29z 0,10 z

koszt()

koszt()

0,20 z

to robi,
(O tym, jak on
a stron dalej).
lk
ki
dowiesz si

2 Dekorator Bitamietana
zt()
wywouje metod kos
.
ada
kol
Cze
a
tor
dekora

Czekolada wywouje metod


koszt() obiektu MocnoPalona.

koszt()
na
ocnoPalo

0,99 zM

zekolada
Bit
amie ana
t

Dekorator Bitamietana dodaje


swj koszt, czyli 10 groszy, do
wyniku uzyskanego od dekoratora
Czekolada i zwraca cakowity
koszt napoju 1,29 z.

Obiekt MocnoPalona
zwraca swj koszt,
czyli 99 groszy.

swj koszt,
Dekorator Czekolada dodaje
jaki uzyska
czyli 20 groszy, do wyniku,
nastpnie
od obiektu MocnoPalona, a
z.
1,19
li
czy
zwraca ca sum,

Podsumujmy zatem, czego dowiedzielimy si do tej pory

Obiekty dekorujce s tego samego typu, co obiekty dekorowane.

Jeden obiekt podstawowy moe zosta zawinity zarwno w jeden, jak i w wiksz ilo
dekoratorw.

Przy zaoeniu, e dekorator jest tego samego typu, co obiekt dekorowany, moemy przekazywa
obiekt owinity dekoratorem zamiast obiektu oryginalnego.

Dekorator dodaje swoje wasne zachowania przed delegowaniem do obiektu dekorowanego


waciwego zadania i (lub) po nim.

Obiekty mog by dekorowane w dowolnym momencie, czyli moemy je rwnie dekorowa


dynamicznie w czasie dziaania programu, uywajc do tego takiej liczby dekoratorw, jaka nam
bdzie potrzebna.

A teraz zobaczymy, jak to naprawd dziaa przyjrzymy si


definicji wzorca Dekorator, a take napiszemy nieco kodu.
120

Kluczow

Rozdzia 3

ienie
e zagadn

Wzorzec Dekorator

Definicja wzorca Dekorator


Przede wszystkim przyjrzyjmy si denicji wzorca Dekorator:
Wzorzec Dekorator pozwala na dynamiczne przydzielanie
danemu obiektowi nowych zachowa. Dekoratory daj
elastyczno podobn do tej, jak daje dziedziczenie,
oferujc jednak w zamian znacznie rozszerzon
funkcjonalno.

Powysza denicja opisuje nam jedynie przeznaczenie wzorca Dekorator, ale nie daje nam niemal
adnych wskazwek, w jaki sposb moglibymy zaimplementowa ten wzorzec w naszej aplikacji.
Rzumy okiem na diagram klas, ktry nieco rozjani nam ca sytuacj (na nastpnej stronie
zobaczymy t sam struktur, wykorzystan do rozwizania naszego problemu z napojami).
uyty samodzielnie
Kady skadnik moe by
oratorem.
bd te w poczeniu z dek

Skadnik

skadnik

metodaA()
metodaB()
// inne metody

SkadnikPodstawowy to obiekt,
ktremu bdziemy dynamicznie
dodawali nowe zachowania. Obiekt
dziedziczy z klasy Skadnik.

Kady dekorator posiada swj skadnik


podstawowy, co oznacza, e kady
dekorator posiada zmienn obiektow,
ktra przechowuje odwoanie do
danego obiektu dekorowanego.

SkadnikPodstawowy
metodaA()
metodaB()
// inne metody

iada zmienn
DekoratorPodstawowy pos
odwoanie
uje
ow
ech
prz
ra
obiektow, kt
wanego.
do danego obiektu dekoro

Dekorator
metodaA()
metodaB()
// inne metody

y
zaimplementowan
Dekoratory maj
s
kla
d
js b
taki sam interfe
ie
obiekt, ktry bdz
abstrakcyjn, jak
dekorowany.

DekoratorPodstawowyA

DekoratorPodstawowyB

Skadnik obiektDekorowany

Skadnik obiektDekorowany
Obiekt nowyStan

metodaA()
metodaB()
noweZachowanie()
// inne metody

metodaA()
metodaB()
// inne metody

owywa
Dekoratory mog rozbud
nika)
ad
(sk
u
ekt
obi
ego
stan dan
dekorowanego.

Dekoratory mog dodawa nowe metody, aczkolwiek zazwyczaj nowe


zachowania s dodawane poprzez wykonywanie oblicze przed ich
realizacj przez metody obiektu dekorowanego lub po niej.

jeste tutaj

121

Dekorujemy napoje

Dekorujemy nasze Napoje


Sprbujemy teraz wtoczy napoje firmy Star Caf w ramy diagramu klas
wzorca Dekorator
Klasa Napoje funk
cjonuje jak nasza
abstrakcyjna klasa
skadnikw.
Napj

skadnik

opis

pobierzOpis()
koszt()
// Inne uyteczne metody...

SkadnikDekorator

MocnoPalona

StarCafeSpecial

pobierzOpis()

koszt()

koszt()

Bezkofeinowa

Espresso

koszt()

koszt()

w
adnik
klasy sk o jednym na .
y
r
e
t
z
p
y
C
h,
nek kaw
wowyc
podsta rowany gatu
e
f
kady o

Mleko

Czekolada

Bitamietana

MleczkoSojowe

Napj napj

Napj napj

Napj napj

Napj napj

pobierzOpis()
koszt()

pobierzOpis()
koszt()

pobierzOpis()
koszt()

pobierzOpis()
koszt()

A tutaj mamy nasze dekoratory (dodatki); zwr uwag, e musz


one mie zaimplementowan nie tylko metod koszt(), ale rwnie
metod pobierzOpis(). Niebawem dowiesz si, dlaczego tak si
dzieje

Wysil szare
komrki
Zanim przejdziesz dalej, pomyl, w jaki sposb zaimplementowaby
metod koszt() dla poszczeglnych gatunkw kawy oraz dodatkw.
Zastanw si rwnie, jak zaimplementowaby metod pobierzOpis()
dla poszczeglnych dodatkw.

122

Rozdzia 3

Wzorzec Dekorator

Zasyszane w ssiednim boksie


Zamieszanie z Dziedziczeniem i Kompozycj

aria

Przepraszam, ale wszystko


mi si ju pokrcio Mylaam, e
gdy bdziemy wykorzystywa ten wzorzec,
nie bdziemy uywali dziedziczenia, ale
kompozycji.

Sandra: Co przez to rozumiesz?


Maria: Spjrz na diagram klas. Klasa SkadnikDekorator jest rozszerzeniem klasy Napj. Przecie to nic

innego, jak wanie dziedziczenie, prawda?

Sandra: Prawda. Myl jednak, e najwaniejsz spraw jest fakt, e dekoratory s tego samego typu
co obiekty, ktre maj by dekorowane. Krtko mwic, uywamy tutaj dziedziczenia po to, aby osign
zgodno typw, a nie po to, aby otrzyma okrelone zachowania.
Maria: No dobrze, rozumiem, e dekoratory potrzebuj tego samego interfejsu co skadniki
dekorowane, poniewa w zasadzie wystpuj one w miejsce rzeczywistych skadnikw. Ale skd w takim
razie pochodz poszczeglne zachowania?
Sandra: Kiedy tworzymy (metod kompozycji) nowy dekorator dla danego skadnika, wtedy wanie
dodajemy nowe zachowania. Krtki mwic, nowe zachowania tworzone s nie poprzez dziedziczenie
z klasy nadrzdnej, ale przez kompozycj poszczeglnych obiektw.
Maria: OK, czyli tworzymy klasy podrzdne dla superklasy Napj nie po to, aby dziedziczy zachowania,
ale po to, aby uzyska zgodno typw poszczeglnych obiektw. Dane zachowania bior si
z kompozycji dekoratorw z poszczeglnymi obiektami, jak rwnie i z innymi dekoratorami.
Sandra: Zgadza si.
Maria: Ooooo, teraz to rozumiem. A poniewa uywamy kompozycji obiektw, dysponujemy o wiele
wiksz elastycznoci w czeniu i dobieraniu dodatkw z napojami. Sprytne.

Sandra: Tak to ju jest, e jeli polegamy tylko na mechanizmie dziedziczenia, wszystkie zachowania
mog by ustalane statycznie w czasie kompilacji programu. Innymi sowy, otrzymujemy wtedy wycznie
zachowania, ktre daje klasa nadrzdna lub ktre zostaj przesonite przez metody w klasach
podrzdnych. Natomiast przy uyciu kompozycji moemy miesza i dobiera dekoratory w niemal
dowolny sposb i to dynamicznie, w trakcie dziaania programu.
Maria: I jeeli dobrze rozumiem, w dowolnym momencie moemy zaimplementowa nowe dekoratory,

ktre zapewni nam nowe zachowania. Jeeli polegalibymy tylko na mechanizmie dziedziczenia,
musielibymy modykowa istniejcy kod za kadym razem, kiedy chcielibymy dooy nowe
zachowania.

Sandra: Dokadnie tak.


Maria: Mam jeszcze tylko jedno pytanie. Jeeli wszystko, czego potrzebujemy od dziedziczenia, to tylko
prawidowy typ skadnika, dlaczego nie uy zamiast abstrakcyjnej klasy Napj po prostu interfejsu?

Sandra: Niby mona, ale pamitaj, e kiedy otrzymalimy ten kod od rmy Star Caf, abstrakcyjna
klasa Napoje ju bya tam zdeniowana. Tradycyjnie wzorzec Dekorator nie wymienia skadnika
abstrakcyjnego, ale w jzyku Java oczywicie moglibymy uy interfejsu. Pamitaj jednak, e zawsze
staramy si unikn modykacji istniejcego kodu, wic nie starajmy si tego naprawi tak dugo,
jak klasa abstrakcyjna spenia swoje zadanie.
jeste tutaj

123

Wzorzec Dekorator trening

Szkolenie nowego barmana


Narysuj schemat tego, co si dzieje, kiedy bar otrzymuje zamwienie
na kaw z podwjn czekolad, mleczkiem sojowym i bit mietan.
Skorzystaj z cen podanych w menu na rysunku obok i narysuj schemat
w takim samym formacie, jakiego uywalimy kilka stron wczeniej:

OK, poprosz kaw


z podwjn czekolad,
mleczkiem sojowym i bit
mietan.

na wywouje
2 Dekorator Bitamieta
olada.
a Czek
metod koszt() dekorator

pierwsze, wywoujemy
1 Po
metod koszt() najbardziej
zewntrznego dekoratora,
jakim jest Bitamietana.

0.10z

1.29z

koszt()

koszt()

koszt()

0.99z

0.20z

Czekolada

na
MocnoPalo

Bit
amietana

Deko
rator
Bita
swj
m
ko
wynik szt, czyli ietana do
daje
10 gro
u uzy
Czek
sk
szy, d
aneg
ola
koszt da i zwra o od deko o
ratora
ca ca
napo
kow
ju
ity
1,29
z.

Dekorator Czekolada wywouje


metod koszt() obiektu MocnoPalona.

imy dla
przygotowal
Ten schemat mocno palon kaw
na
zamwienia t mietan.
i bi

ad
z czekol

Obiekt MocnoPalona
zwraca swj koszt, czyli
99 groszy.

swj koszt,
Dekorator Czekolada dodaje
jaki uzyska od
czyli 20 groszy, do wyniku,
nie zwraca
obiektu MocnoPalona, a nastp
ca sum, czyli 1,19 z.

Zaostrz owek

Schemat narysuj tutaj.

Star Caf
Kawy
Star Cafe
Special
Mocno Palona
Bezkofeinowa
Espresso

0,89 z
0,99 z
1,05 z
1,99 z

Dodatki
Mleko
10
Czekolada
20
Mleczko sojowe
15
Bita mietana
10

Caf Sta

,
kolad
cze moesz
jn

z pod mietan wy
kaw
ka
it
wka: wym i b porcj leczka

z
a
Wsk kiem sojo rc jedn orcj m z
a
p
z
io
mlec zdzi, b ial, jedn kolady or
e
r
c
przy afe Spe porcje cz y.
C
n
Star ego, dwie ej mieta
sojow porcj bit
jedn
Ca

f Star Ca

124

Star Caf
f

Caf
S
tar

r
Sta

Rozdzia 3

gr
gr
gr
gr

Wzorzec Dekorator

Tworzymy kod aplikacji Star Caf


Nadszed ju czas, abymy zamienili nasz projekt
aplikacji w rzeczywisty kod programu.
Rozpoczniemy od definicji klasy Napj, ktrej kod nie bdzie
si w niczym rni od oryginau otrzymanego od firmy Star
Caf. Przypomnij sobie, jak on wyglda:
kcyjn, ktra
st klas abstra
Klasa Napj je
pis() oraz
etody: pobierzO
posiada dwie m
koszt()

public abstract class Napj {


String opis = "Napj nieznany";
public String pobierzOpis() {
return opis;
}
public abstract double koszt();
}

Metoda pobierzOpis() zostaa ju


wczeniej zaimplementowana, ale musimy
jeszcze zaimplementowa metod koszt()
w poszczeglnych klasach podrzdnych.

Kod klasy Napj jest wystarczajco prosty. Teraz utworzymy


kod klasy abstrakcyjnej SkadnikDekorator:
ni zgodno
musimy zapew
im
tk
ys
sz
w
e
Przed
sza klasa
Napj, std na
typw z klas
apj (klasa
N
y
as
kl
eniem
bdzie rozszerz dziedziczy po klasie Napj).
ator
SkadnikDekor
public abstract class SkadnikDekorator extends Napj {
public abstract String pobierzOpis();
}

Bdziemy rwnie wymagali, aby poszczeglne


skadniki dodatkw (dekoratory) posiaday
zaimplementowan metod pobierzOpis().
Dlaczego tak powinno by, przekonasz si ju
za chwil

jeste tutaj

125

Implementacja napojw

Tworzenie kodu klas opisujcych napoje


Mamy ju gotowy kod naszych klas bazowych, wic nadszed czas na
implementacj poszczeglnych napojw. Rozpoczniemy od znanego wszystkim
Espresso. Pamitaj, e dla kadego napoju musimy utworzy opis (czyli
ustawi warto zmiennej opis) oraz zaimplementowa metod koszt().

public class Espresso extends Napj {


public Espresso() {
opis = "Kawa Espresso";
}
public double koszt() {
return 1.99;
}

dziczy
a Espresso dzie
Poniewa klas
tpliwie
, sama jest niew
po klasie Napj
napojem.

y warto
Aby dooy opis do napoju, ustawiam
. Pamitaj,
klasy
tej
e
torz
truk
kons
w
zmiennej opis
zona z klasy
dzic
e zmienna obiektowa opis jest dzie
nadrzdnej Napj.

i
artwi o dodatk
ie musimy si m
N
.
so
es
i
pr
yl
Es
cz
y
,
t kaw
presso
y wyliczy kosz
i cen kawy Es
W kocu musim
camy bezporedn
ra
zw
tu
os
pr
c po
i ich koszty, wi
dku 1,99 z.
pa
zy
pr
ym
sz
na
w

public class StarCafeSpecial extends Napj {


public StarCafeSpecial() {
opis = "Kawa Star Cafe Special";
}
public double koszt() {
return 0.89;
}
}

Tutaj mamy definicj kolejnego Napoju. Caa nasza


praca sprowadza si do ustawienia wartoci zmiennej
opis (Specjalno firmy Star Cafe Special) oraz
zwracania prawidowej ceny napoju, czyli 0,89 z.

Definicje pozostaych dwch klas napojw (MocnoPalona oraz


Bezkofeinowa) moesz utworzy dokadnie w taki sam sposb.

126

Rozdzia 3

Star Caf
Kaw y
afe
Star C
0,89 z
l
a
i
c
e
Sp
0,99 z
Palona ,05 z
Mocno
1
einowa
Bezkof
1,99 z
o
s
s
e
r
p
Es
i
10 gr
Dodatk
o
k
e
20 gr
Ml
ada
l
r
o
k
e
z
C
we 15 g
o sojo
r
g
0
1
Mleczk
ietana
m

a
t
Bi

Wzorzec Dekorator

Tworzenie kodu klas opisujcych dodatki


Jeeli przypomnisz sobie, jak wyglda diagram klas wzorca Dekorator,
zorientujesz si, e utworzylimy ju nasz skadnik abstrakcyjny (klasa Napj),
mamy gotowe poszczeglne skadniki (klasy StarCafeSpecial i inne) oraz gotowy
dekorator abstrakcyjny (klasa SkadnikDekorator). Nadszed zatem czas na
implementacj poszczeglnych dekoratorw. Oto definicja klasy Czekolada:
dziczy
tor dzie
a
r
o
k
e
ikiD
sy Czekolada,
Skadn
orzy obiekt kla
w
aj, klasa
ut
t
r
ia
i
m
Napj,
za
m
y
a
Mam
oje.
Czekolada jest dekoratorem, wic dziedziczy P
do obiektu klasy
sie Nap
ie si odwoywa
la
dz
k
b
y
o
r
p
kt
po klasie SkadnikDekorator.
wykorzystujc:
c dekorowany
tow przechowuj
(1) Zmienn obiek
public class Czekolada extends SkadnikDekorator {
obiekt.
Napj napj;
tej zmiennej
sposb ustawiania
j mamy zamiar
(2) Specyficzny
Tu
wany obiekt. ta
ro
j
ko
de
na
ej
w
public Czekolada(Napj napj) {
obiekto
dekorowany nap
t reprezentujcy
iek
ob
a
w
zy
ka
ze
this.napj = napj;
pr
dekoratora.
}
do konstruktora
public String pobierzOpis() {
return napj.pobierzOpis() + ", Czekolada";
}
public double koszt() {
return 0,20 + napj.koszt();
}
}

jpierw
tkiem czekolady. Na
cen napoju z doda
zy
tak
lic
tu,
wy
y
iek
ob
sim
go
mu
z
ne
ra
Te
szt() do dekorowa
ko
y
tod
me
nie
na
do
ko
delegujemy wy
y koszt czekolady
, a nastpnie dodajem
aby uzyska jego koszt
uzyskanego rezultatu.

Chcemy, aby opis obejmowa nie tylko nazw napoju


przykadowo Mocno Palona ale rwnie
nazwy kadego dodatku uytego do dekorowania,
przykadowo Mocno Palona, Czekolada. Z tego
wzgldu najpierw delegujemy wykonanie metody
pobierzOpis() do dekorowanego obiektu (co pozwala
na pobranie jego opisu), a nastpnie doczamy opis
naszego dekoratora, Czekolada, do uzyskanego
wyniku.

Na nastpnej stronie utworzymy wreszcie nasz napj i wzbogacimy


go rnymi dodatkami (dekoratorami), ale najpierw

Zaostrz owek

Napisz i skompiluj odpowiedni kod programu deniujcy


dodatki MleczkoSojowe oraz Bitamietana. Bdziesz go
potrzebowa do uruchomienia i testowania caej aplikacji.

jeste tutaj

127

Testowanie napojw

Podajemy kaw
Gratulacje. Nadszed czas, aby spokojnie usi, zamwi kilka lianek
aromatycznej kawy i w caej rozcigoci podziwia elastyczno projektu,
ktry stworzylimy przy wykorzystaniu wzorca Dekorator.
Oto prosty kod, ktry umoliwia przeprowadzenie testw* naszej aplikacji:
public class StarCafe {

atkw)

d
o (bez do
Espress .
w
a
k
ia
w

Zama
az cen
jej opis or
i drukuje

public static void main(String args[]) {


Napj napj = new Espresso();
System.out.println(napj.pobierzOpis() + " " +
+ napj.koszt() + " z");
MocnoPalona.
Utwrz obiekt
Napj napj2 = new MocnoPalona();
Udekoruj go Czekolad.
napj2 = new Czekolada(napj2);
Udekoruj drug porcj Czekolady.
napj2 = new Czekolada(napj2);
Udekoruj Bitmietan.
napj2 = new Bitamietana(napj2);
System.out.println(napj2.pobierzOpis() + " " +
+ napj2.koszt() + " z");
Napj napj3 = new StarCafeSpecial();
napj3 = new MleczkoSojowe(napj3);
napj3 = new Czekolada(napj3);
napj3 = new Bitamietana(napj3);
System.out.println(napj3.pobierzOpis() + "
+ napj3.koszt()+ " z");

Wreszcie poprosimy o kaw


ym,
StarCafeSpecial, z MleczkiemSojow
.
etan
mi
Bit
oraz
Czekolad
" +

}
}

128

Znacznie lepszy sposb tworzenia obiektw dekorowanych


poznasz przy okazji omawiania wzorcw Fabryka oraz Builder.
Uwaga opis wzorca Builder znajdziesz w dodatku.

Rozdzia 3

Wzorzec Dekorator

Nie ma niemdrych pyta

P:

Zastanawiam si nad
funkcjonowaniem kodu, ktry
testowaby tylko wybrane skadniki
powiedzmy, kaw StarCafeSpecial
i wykonywa jak operacj, np.
udziela rabatu na ten gatunek kawy.
W sytuacji, kiedy taki kod zostaby
zawinity w jeden lub wicej
dekoratorw, przestaby przecie
dziaa.

O:

Masz cakowit racj. Jeeli przygotujesz


kod, ktry jest uzaleniony od konkretnego typu
skadnika, dekorator uniemoliwi jego dziaanie.
Dopty, dopki tworzysz kod aplikacji w oparciu
o definicj klasy abstrakcyjnej, zastosowanie
dekoratorw bdzie dla niego cakowicie
przezroczyste. Jeeli jednak zaczniesz opiera swj
kod o konkretne implementacje poszczeglnych
skadnikw, z pewnoci bdziesz musia przemyle
projekt aplikacji i zastosowanie dekoratorw.

P:

Czy przypadkiem w pewnych


sytuacjach nie moe si zdarzy tak,
e cay proces wyliczania kosztw
zakoczy si nie na zewntrznym,
ale na ktrym z wewntrznych
dekoratorw? Przykadowo, jeeli
zamwimy kaw MocnoPalona
z Czekolad, MleczkiemSojowym
i Bitmietan, w zasadzie mona
dosy atwo popeni bd i napisa
kod, ktrego realizacja zakoczy
si, dajmy na to, na odwoaniu
do MleczkaSojowego zamiast do
Bitejmietany. W takiej sytuacji
Bitamietana nie zostanie w ogle
uwzgldniona w zamwieniu.

O:

Oczywicie, moesz tutaj susznie


argumentowa, e korzystajc z wzorca Dekorator,
musisz zarzdza wiksz liczb obiektw,
std istnieje zwikszone prawdopodobiestwo
popenienia bdu w kodzie programu
i w konsekwencji wystpienia np. opisywanych
w pytaniu bdw. Naley jednak pamita
o tym, e zazwyczaj do tworzenia dekoratorw
uywa si innych wzorcw projektowych, takich
jak np. Fabryka czy Builder. Kiedy omwimy te
wzorce, przekonasz si, e tworzenie rzeczywistej
implementacji skadnika cznie z jego dekoratorem
jest dobrze hermetyzowane i nie bdzie
powodowao takich problemw.

P:

Czy dany dekorator posiada


jak wiedz o innych dekoratorach
w danym acuchu przetwarzania?
Przykadowo, zamy, e chc,
aby moja metoda pobierzOpis()
drukowaa taki opis: Bita mietana,
podwjna Czekolada zamiast
Czekolada, Bita mietana, Czekolada?
Takie rozwizanie wymagaoby tego,
aby najbardziej zewntrzny dekorator
zna wszystkie wewntrzne dekoratory.

O:

Dekoratory zostay pomylane


w ten sposb, aby dodaway nowe zachowania
do obiektw dekorowanych. Jeeli chcesz
zajrze w gb, do dekoratorw znajdujcych
si na poszczeglnych poziomach acucha
przetwarzania, niejako zaczynasz wypycha
dekoratory daleko poza granic tego, do czego
tak naprawd zostay stworzone. Jednak takie
rozwizania s moliwe. Wyobra sobie dekorator
DodatkiFormatujWydruk, ktry dokonuje finalnej
analizy otrzymanego opisu i potrafi wydrukowa
opis w postaci Bita mietana, podwjna
Czekolada zamiast Czekolada, Bita mietana,
Czekolada. Zauwa, e aby uatwi realizacj
takiego zadania, metoda pobierzOpis() mogaby
zwraca wynik w postaci typu ArrayList.

Zaostrz owek
Nasi przyjaciele ze Star Caf wprowadzili do menu wielkoci kawy.
Obecnie moesz kupi kaw w trzech rozmiarach: ma, redni i du.
Specjalici ze Star Caf stwierdzili, e takie elementy powinny by
nieodczn czci klasy opisujcej napoje, std dodali do klasy Napj
dwie metody: ustawWielko() oraz pobierzWielko(). Chcieli rwnie,
aby poszczeglne dodatki byy wyceniane w zalenoci od wielkoci napoju,
przykadowo, MleczkoSojowe bdzie kosztowao 10 gr, 15 gr oraz 20 gr
odpowiednio dla maej, redniej i duej kawy.
W jaki sposb naleaoby zmodykowa klasy opisujce dekoratory,
aby mogy one sobie poradzi z powyszym zadaniem?
jeste tutaj

129

Dekoratory w pakiecie java.io

Dekoratory w wiecie rzeczywistym:


obsuga wejcia-wyjcia w jzyku Java
Ogromna ilo klas dostpnych w pakiecie java.io jest po prostu przytaczajca. Na pocieszenie
powiemy Ci jednak, e jeeli widzc po raz pierwszy (a nawet po raz drugi i trzeci) list klas
tego pakietu, wrzasne Uuuuaaa!, z pewnoci nie bye w tym odosobniony. Co wicej,
teraz, kiedy ju poznae wzorzec Dekorator, te wszystkie klasy z pakietu java.io powinny by dla
Ciebie o wiele bardziej zrozumiae, jako e pakiet ten powsta w duej mierze w oparciu wanie
o wzorzec Dekorator. Poniej przedstawilimy typowy zestaw obiektw, ktre wykorzystuj
dekoratory do modykacji zachowa przy odczycie danych z pliku:
Plik tekstowy przeznaczony do odczytu.

Li

Bu

ne

Num

Obiekt LineNumberInputStream
rwnie jest dekoratorem, ktrego
zadaniem jest umoliwienie
policzenia iloci odczytywanych
wierszy danych.

F il e I n p u t S t r e a m

ffe

redIn

putStream

ber I n p u t S t r eam
Obiekt BufferedInputStream jest
ream
dekoratorem. Klasa BufferedInputSt
:
owa
zach
ych
now
aje
rodz
dodaje dwa
danych
ia
mien
stru
anie
row
bufo
wnia
zape
caego
wejciowych, co polepsza wydajno
interfejs,
uje
udow
rozb
nie
procesu, jak rw
Line(),
dodajc do niego now metod read
pliku
z
ch
dany
ktra pozwala na odczyt
z.
tekstowego po jednym wierszu nara

.
skadnikiem
orowanym
ek
d
st

je
ug
m
s
ch ob
InputStrea
pewniajcy dnych
Obiekt File
ka Java, za
ezb
zy
ni
j
s
a
eg
kl
er
Biblioteka
zawiera sz
,
ia
c
yj
-w
cia
Stream,
operacji wej ch jak klasy FileInput
m
ki
yInputStrea
, ta
ByteArra
,
skadnikw
m
ea
tr
S
rInput
StringBuffe
.
ch
ny
in
i wiele

Klasy BufferedInputStream oraz LineNumberInputStream s rozszerzeniem klasy


FilterInputStream, ktra odgrywa rol abstrakcyjnej klasy dekoratora.

130

Rozdzia 3

Wzorzec Dekorator

Dekorowanie klas pakietu java.io

a
Oto nasz sk

kcyjny.
dnik abstra

Klasa FilterInputStream
jest dekoratorem
abstrakcyjnym.
InputStream

FileInputStream

StringBufferInputStream

PushbackInputStream

Te strumienie danych wejciowych


funkcjonuj jako skadniki, ktre bd
dekorowane. Oczywicie, istnieje
wicej takich skadnikw, ktre nie
zostay tu pokazane, jak choby klasa
ObjectInputStream.

FilterInputStream

ByteArrayInputStream

BufferedInputStream

DataInputStream

LineNumberInputStream

entacje
I wreszcie tutaj mamy implem
w.
poszczeglnych dekorator

Jak sam zapewne zauwaye, powyszy diagram klas wcale tak bardzo
nie rni si od naszego projektu aplikacji dla Star Caf. Obecnie nie
powiniene mie ju wikszych trudnoci ze zrozumieniem podrcznikw
uytkownika pakietu java.io API, jak rwnie z samym tworzeniem
dekoratorw dla rnych strumieni danych wejciowych.
Niebawem przekonasz si, e strumienie danych wyjciowych maj tak sam
struktur. Zapewne zorientowae si ju, e strumienie Reader oraz Writer
(odpowiednio dla wejcia i wyjcia danych znakowych) s niemal dokadnym
odzwierciedleniem struktury klas strumieni (z kilkoma wprawdzie drobnymi
rnicami i niekonsekwencjami, ale na tyle maymi, e mona bez trudu
zrozumie zasady ich funkcjonowania).
Z drugiej strony, pakiet java.io odsania rwnie jedn z najciemniejszych stron
wzorca Dekorator: projekty budowane z wykorzystaniem tego wzorca czsto
charakteryzuj si powstawaniem duej iloci niewielkich klas, ktre pniej
mog stanowi powane utrudnienie dla projektanta chccego skorzysta
z opartego na tym wzorcu API. Teraz jednak, kiedy ju doskonale znasz zasady
funkcjonowania wzorca Dekorator, moesz na takie zjawisko zwraca wiksz
uwag; kiedy za bdziesz korzysta z czyjego API przepenionego rnymi
dekoratorami, z pewnoci atwiej bdzie Ci si zorientowa w caej strukturze
klas i wykorzystywa poszczeglne dekoratory w sposb zapewniajcy
osignicie optymalnych, danych rezultatw.

jeste tutaj

131

Tworzenie wasnych dekoratorw obsugi wejcia-wyjcia

Tworzenie wasnych dekoratorw obsugi wejcia-wyjcia


OK, znasz ju zasady funkcjonowania wzorca Dekorator, widziae te
diagram klas zapewniajcych obsug operacji wejcia-wyjcia. Krtko
mwic, powiniene by gotowy do napisania swojego wasnego dekoratora
obsugujcego strumie danych wejciowych.
Co sdzisz o tym: napisz dekorator, ktrego zadaniem bdzie konwersja
wszystkich liter duych na litery mae w strumieniu danych wejciowych.
Innymi sowy, jeeli w strumieniu danych wejciowych pojawi si
nastpujcy acuch alfanumeryczny: Znam wzorzec dekorator,
zatem to Ja tutaj USTALAM ZASADY!, Twj dekorator dokona
konwersji tego acucha do nastpujcej postaci: znam wzorzec
dekorator, zatem to ja tutaj ustalam zasady!.

pakietu
importowa
za
j
ni
om
p
e zosta
Nie za
iedni kod ni
ow
p
d
(o
.io
java
ny).
tutaj pokaza

aden kopot. Po prostu musz utworzy


klas podrzdn do klasy FilterInputStream
(rozszerzajc funkcjonalno klasy
FilterInputStream) i przesoni w niej
metod read().

bdzie
Przede wszystkim musimy utworzy now podklas, ktra
torze
dekora
m
kcyjny
abstra
am,
utStre
FileInp
dziedziczy po klasie
).
tream
InputS
(xxxxx
owych
wejci
ieni
strum
klas
tkich
wszys

public class LowerCaseInputStream extends FilterInputStream {


public LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char)c));
}

132

public int read(byte[] b, int offset, int len) throws IOException {


int result = super.read(b, offset, len);
for (int i = offset; i < offset+result; i++) {
Teraz musimy zaimplementowa dwie
b[i] = (byte)Character.toLowerCase((char)b[i]);
metody read(), ktrych zadaniem jest
}
PAMITAJ: w naszych przykadach nie zamieszczamy
odczytywanie danych. Pobieraj one
return result;
fragmentw kodu odpowiedzialnych za import i obsug
pojedynczy znak (bajt) lub tablic znakw
}
poszczeglnych pakietw bibliotek jzyka Java. Kompletny zestaw
(tablic bajtw), a nastpnie dokonuj
kodw rdowych przykadw zamieszczonych w naszej ksice
konwersji kadego znaku (kady bajt
moesz pobra z serwera FTP wydawnictwa Helion:
reprezentuje jeden znak) do postaci
ftp://ftp.helion.pl/przyklady/hfdepa.zip
maych liter.

Rozdzia 3

Wzorzec Dekorator

Testowanie nowego dekoratora


obsugujcego wejcie-wyjcie
Napiszemy teraz szybko nieco kodu, ktrego zadaniem
bdzie testowanie naszego nowego dekoratora:
public class InputTest {
public static void main(String[] args) throws IOException {
int c;
try {
InputStream in =
new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("test.txt")));

tStream
klasy FileInpu
kt
ie
ob
zy
Twor
iektami
koruje go ob
de
e
ni
ym nowym
p
st
i na
m oraz nasz
ea
tr
S
ut
np
BufferedI
Stream.
erCaseInput
filtrem Low

while((c = in.read()) >= 0) {


System.out.print((char)c);
}

in.close();
} catch (IOException e) {
e.printStackTrace();
}
Korzystajc ze strumienia danych,
odczytujemy dane z pliku i na bieco
drukujemy je na ekranie.

Odpalamy program:

Znam wzorzec Dekorator, zatem to Ja tutaj USTALAM ZASADY!

plik test.txt
orzy ten
Musisz utw
elnie.
plik samodzi

jeste tutaj

133

Wywiad z wzorcem Dekorator

Wzorce bez tajemnic


Wywiad tygodnia:
Wyznania Dekoratora
HeadFirst: Spotykamy si dzisiaj z wzorcem Dekorator. Syszelimy, e ostatnio miae ze sob pewne
kopoty?

Dekorator: Tak. Wiem, e wszyscy naokoo widz mnie jako wspaniay wzorzec projektowy, podczas
gdy sam wiesz, jak to jest musz sobie radzi z rnymi problemami, tak jak kady z nas.

HeadFirst: To moe podzielisz si swoimi problemami rwnie z nami?


Dekorator: Oczywicie, czemu nie. Jak sam wiesz, posiadam moc dodawania projektom elastycznoci
i to jest naprawd co ale, niestety, rwnie mam swoje ciemne strony. Widzisz, czasami zbytnio si
rozpdzam i powoduj, e w projekcie pojawia si ogromna ilo maych klas, co moe spowodowa,
e staje si on nieco zbyt zagmatwany i trudny do zrozumienia dla innych programistw.

HeadFirst: Czy moesz nam zaprezentowa jaki konkretny przykad?


Dekorator: Wemy pakiet bibliotek java.io. Wrd programistw ciesz si one, niestety, zasuon opini

mao przyjaznych i trudnych do zrozumienia na pierwszy rzut oka. Jeeli jednak oni zrozumieliby, e cay
ten zestaw rnych klas to po prostu zestaw dekoratorw zbudowanych dookoa klas InputStream, ich ycie
staoby si o wiele atwiejsze.

HeadFirst: Ale to przecie nie wyglda le. W niczym nie zmienia to faktu, e nadal jeste wspaniaym
wzorcem, a caa reszta to po prostu kwestia odpowiedniej edukacji i szkolenia, prawda?

Dekorator: No... niestety, obawiam si, e jest co jeszcze. Mam pewne problemy z kodem: widzisz,

niektrzy ludzie po prostu bior odpowiedni fragment kodu klienta, ktry operuje na okrelonych typach
obiektw, i wprowadzaj dekoratory, nie mylc ju o niczym innym. Jedn z moich naprawd wspaniaych
cech jest to, e w wikszoci przypadkw dekoratory moesz wstawi w sposb cakowicie przezroczysty
i klient nigdy nie musi by poinformowany, e je wykorzystuje. Ale, niestety jak ju wspomniaem
niektre partie kodu s uzalenione od okrelonych typw obiektw i kiedy zaczniesz wprowadza
do takiego ukadu dekoratory, robi si mae Bum!. I zaczyna by naprawd le.

HeadFirst: Wiesz co, myl jednak, e wszyscy doskonale zdaj sobie spraw, e przy wprowadzaniu

dekoratorw do kodu naley zachowa pewn ostrono. Nie sdz, aby by to wystarczajcy powd
do robienia sobie powanych wyrzutw.

Dekorator: No wiem, wiem, i mimo wszystko staram si tego nie robi. Innym problemem, z ktrym

si musz boryka, jest to, e wprowadzenie dekoratorw do aplikacji moe spowodowa wzrost stopnia
zoonoci kodu niezbdnego do prawidowego tworzenia obiektw poszczeglnych klas skadnikw.
Kiedy korzystasz z dekoratorw, musisz nie tylko utworzy sam obiekt danej klasy, ale jeszcze dodatkowo
opakowa go Bg wie iloma dekoratorami.

HeadFirst: Na przyszy tydzie mam ju zaplanowany wywiad z wzorcami Fabryka oraz Builder
syszaem, e one mog by wielce pomocne przy rozwizywaniu tego problemu?

Dekorator: To prawda; w zasadzie powinienem czciej si z nimi spotyka.


HeadFirst: Mimo to i tak wszyscy wiemy, e jeste wspaniaym wzorcem projektowym, umoliwiajcym

tworzenie elastycznych projektw pozostajcych w zgodzie z regu otwarte-zamknite, wic nie przejmuj
si niczym, gowa do gry i myl pozytywnie!

Dekorator: Postaram si, dzikuj bardzo.

134

Rozdzia 3

Wzorzec Dekorator

Twoja skrzynka narzdziowa


Masz ju za sob kolejny rozdzia
i nowe reguy i wzorce znalazy si
w Twojej narzdziowni.

programoPo d s t a w y
ktowego
w a n ia o b ie
o

gramowaReguy pro
wego
n ia o b ie k t o zacji to, co si zmienia.

h e r m e ty
Po d d a w a j
z ie d z ic z e y c j n a d d
z
o
p
m
o
k
j
da
P r z e d k a
w,
n ie .
in te r fe js
tw o r z e n iu
a
n

si
j
u
S k o n c e n tr n ta c ji .
me
a n ie im p le
w k t r y c h
p r o je k ty,

y
z
r
o
tw
o w i z a n e
S ta r a j si
b lu n o p u j n a
so
e
z
s
o b ie k ty
ie o d d z ia
m o li w e , n
i, o il e to
je m n ie .
si e b ie w z a
te

twar
in n y b y o
K la s y p o w , a le z a m k n i t e
ow
n a r o z b u d je .
ac
n a m o d y f ik

A b st r a k c

y jn

a c ja
H e r m e ty z
m
Po li m o r fi z
e n ie
D z ie d z ic z

Od tej pory bdziemy si rwnie


te.
kierowali regu otwarte-zamkni
a
izow
real
ali
star
si
y
Bdziem
projekty naszych systemw w taki
sposb, aby gotowe, zamknite
e od
elementy byy skutecznie izolowan
e.
zerz
rozs
nas
z
prze
ych
dzan
owa
wpr

ego
o b ie k t o w

a m o w a n ia
r
g
o
r
p
e
c
zy
Wzor
jeinpyo m i d
iu
z
in
f
d
e
o
d
r

je
wd ytnaakmi ic z n e
lu
w adteofrin iu d e n - d o -ewraiem
r
e
s
b
e
a
y
n
O
g
e
la
t
je
h
a
w
Str
r icahpnoyz o b ieb iek tk tzomwiei n- o w y c h
m,iedrkoeola
kroacnjtuoje
btiemk taw
o
D
w
y
r
y
a lg o s p o s b, prez ykddiezudiejela, nieyebdrsatnieae mjjeugsyooidoabjieeklat ys t y c z n o
o w o , aws. zDyesktokcr aSt otrr a toemgioyiendez ici z e n ie ,
t y z a cnjiia ispw zj asctha.onwW
zdooorttzyeemj, japkowdiaa jed d z n ie r o z s z e e
n
n
j
ie
a
t
m

s
n
y
o
n e .z n a c z
o n e wz a le n epzo d o b
t ukawli zzoawmaia n
c zunjiec jez adkn a
a u t o m aotfye r f u n k c jo n a ln o .
rzon

ktry spenia
ec projektowy,
rz
zo
w
y
sz
w
nasz pier
naprawd by
A tutaj mamy
te. Czy jednak
i
kn
y,
am
-z
te
ar
otw
o ju uywalim
wymogi reguy
wzorzec, ktreg
ny
in

ki
ja
st
je
pierwszy? Czy
regu?
by zgodny z t
a ktry rwnie

KLUCZOWE
ZAGADNIENIA

Dziedziczenie jest jedn z form


rozszerzania funkcjonalnoci klasy,
ale niekoniecznie musi by najlepszym
sposobem na osignicie w peni
elastycznych projektw aplikacji.
Tworzc projekt aplikacji, powiniene
tak go skonstruowa, aby moliwe byo
rozszerzanie zachowa poszczeglnych
elementw bez koniecznoci
modyfikowania istniejcego kodu.
Wykorzystujc kompozycj oraz
delegacj, mona dodawa nowe
zachowania podczas dziaania programu.
Wzorzec Dekorator stanowi pod
wzgldem funkcjonalnoci (dodawanie
nowych zachowa) powan
alternatyw dla dziedziczenia.
Wzorzec Dekorator posuguje
si zbiorem klas dekorujcych
(dekoratorw), ktre s wykorzystywane
do dekorowania poszczeglnych
obiektw (skadnikw).
Klasy dekorujce odzwierciedlaj
typy obiektw dekorowanych
(w rzeczywistoci dekoratory s tego
samego typu co obiekty dekorowane,
niezalenie, czy zostao to osignite
metod dziedziczenia, czy implementacji
odpowiednich interfejsw).
Dekoratory zmieniaj zachowania
obiektw dekorowanych (skadnikw),
dodajc nowe zachowania przed
wywoaniami metod danego skadnika
i (lub) po nich (lub nawet pomidzy nimi).

Kady skadnik moe by otoczony


dowoln iloci dekoratorw.

Dekoratory s zazwyczaj cakowicie


przezroczyste dla klientw danego
skadnika tak dugo, jak dugo
funkcjonowanie klienta nie jest
uzalenione od rzeczywistej
implementacji danego skadnika.

Zastosowanie dekoratorw moe


by przyczyn pojawienia si w
projekcie duej iloci maych obiektw;
naduywanie dekoratorw moe
doprowadzi do zdecydowanego
wzrostu zoonoci kodu.

jeste tutaj

135

Rozwizania wicze

Rozwizania wicze
public class Napj {
// deklaracje zmiennych obiektowych mlekoKoszt,
// mleczkoSojoweKoszt, czekoladaKoszt, bitamietanaKoszt

public class MocnoPalona extends Napj {

// oraz odpowiednich metod dla poszczeglnych dodatkw


public MocnoPalona() {
opis = Znakomity, mocno palony gatunek kawy!

public float koszt() {


}
float dodatekKoszt = 0,0;
if (zMlekiem()) {

public float koszt() {

dodatekKoszt += mlekoKoszt;
}

return 1,99 + super.koszt();

if (zMleczkiemSojowym()) {
dodatekKoszt += mleczkoSojoweKoszt;

if (zCzekolad()) {
dodatekKoszt += czekoladaKoszt;
}
if (zBitmietan()) {
dodatekKoszt += bitamietanaKoszt;
}
return dodatekKoszt;
}
}

Szkolenie nowego barmana

kawa z podwjn czekolad, mleczkiem sojowym i bit mietan


wywouje metod

or Bitamietana
2 Dekorat
ratora Czekolada.
koszt() deko

metod koszt()
Dekorator Czekolada wywouje

3 kolejnego dekoratora Czekolada.

metod
Po pierwsze, wywoujemy
znego
koszt() najbardziej zewntr
mietana.
dekoratora, jakim jest Bita

wywouje
Drugi dekorator Czekolada
ojowe.
koszt() dekoratora MleczkoS

5
r
Sta Ca

f
Ca

ar

Star

Caf

0,10 z

koszt()

0,20 z

koszt()

koszt()

koszt()

0,15 z

0,20 z

St

Ml

a
Bit

m
ie

Cz

Metoda koszt() obiektu


StarCafeSpecial zwraca swj
nam
koszt (czyli 89 gr) i schodzi

do metody koszt() dekoratora Bitamietana,


ktry dodaje swj koszt, czyli 10 groszy, do
wyniku uzyskanego od dekoratora Czekolada,
i zwraca cakowity koszt napoju, czyli 1,54 z.

Rozdzia 3

ze stosu.

koszt()

0,89 z

Star
CafeSpecial

ecz
koS
Cz
ojow
eko
e
lada

eko
lada

tana

10 Wreszcie rezultat tego szeregu operacji powraca

136

Ostatni dodatek! Dekorator


d koszt()
MleczkoSojowe wywouje meto
obiektu StarCafeSpecial.

1,54 z

metod

Metoda koszt() dekoratora


u
MleczkoSojowe dodaje do koszt
swoje 15 gr, zwraca wynik tej
operacji i schodzi ze stosu.

ratora
Metoda koszt() drugiego deko
swoje
Czekolada dodaje do kosztu
cji
20 gr, zwraca wynik tej opera
i schodzi ze stosu.

Metoda koszt() pierwszego


do
dekoratora Czekolada dodaje
wynik
kosztu swoje 20 gr, zwraca
.
tej operacji i schodzi ze stosu

Wzorzec Dekorator

Rozwizania wicze
Nasi przyjaciele ze Star Caf wprowadzili do menu wielkoci kawy. Obecnie
moesz kupi kaw w trzech rozmiarach: ma, redni i du. Specjalici ze Star Caf
stwierdzili, e takie elementy powinny by nieodczn czci klasy opisujcej napoje,
std dodali do klasy Napoje dwie metody: ustawWielko() oraz pobierzWielko().
Chcieli rwnie, aby poszczeglne dodatki byy wyceniane w zalenoci od wielkoci
napoju, przykadowo, MleczkoSojowe bdzie kosztowao 10 gr, 15 gr oraz 20 gr
odpowiednio dla maej, redniej i duej kawy.
W jaki sposb naleaoby zmodykowa klasy opisujce dekoratory, aby mogy one sobie
poradzi z powyszym zadaniem?

public class MleczkoSojowe extends SkadnikDekorator{


a metod
zaimplementow
Napj napj;
Teraz musimy
anego napoju.
() do dekorow
pobierzWielko
a t metod
to
zaimplemen w
e
ni
ana
w
public MleczkoSojowe (Napj napj) {
r
y
im
Mus
a bdzie uyw
kcyjnej, poniew
this.napj = napj;
w klasie abstra
ie dekoratory.
}
przez wszystk
public pobierzWielko() {
return napj.pobierzWielko();
}
public String pobierzOpis() {
return napj.pobierzOpis() + ", Mleczko Sojowe";
}
public double koszt() {
double koszt = napj.koszt();
Tutaj pobieramy wielko napoju,
if (pobierzWielko() == Napj.MAY) {
a nastpnie dodajemy do ceny napoju
koszt += 0,10;
odpowiedni koszt dodatku.
} else if (pobierzWielko() == Napj.REDNI) {
koszt += 0,15;
} else if (pobierzWielko() == Napj.DUY) {
koszt += 0,20;
}
return.koszt;
}
}

jeste tutaj

137

You might also like