Wzorce projektowe strukturalne cz. 1 Krzysztof Ciebiera 19 pa¹dziernika 2005 1
1 Wst p 1.1 Podstawowe wzorce Podstawowe wzorce Podstawowe informacje Singleton gwarantuje,»e klasa ma jeden egzemplarz. Adapter dostosowuje jeden interfejs do innego. Kompozyt buduje hierarchi z obiektów prostych i zªo»onych. Peªnomocnik jest przedstawicielem lub substytutem innego obiektu. 2 Singleton 2.1 Denicja Singleton Przeznaczenie Gwarantuje,»e klasa ma tylko jeden egzemplarz, i zapewnia globalny dost p do niego. Przykªad Program buforuj cy dla drukarek. Stosowalno± klasa musi mie tylko dokªadnie egzemplarz, dost pny dla jej klientów; powinno by mo»liwe rozbudowywanie tego jedynego egzemplarza przez deniowanie podklas, a klienci powinni móc u»ywa rozszerzonego egzemplarza bez modykowania swojego kodu. Struktura singletonu
Konsekwencje singletonu Konsekwencje Kontrolowany dost p do jedynego egzemplarza. Mniejsza przestrze«nazw. Mo»liwe udoskonalenie operacji i reprezentacji. Zmienna liczba egzemplarzy. Wi ksza elastyczno± ni» w wypadku operacji klasowych. 2.2 Implementacja Zagwarantowanie unikatowego egzemplarza Deklaracja class Singleton { static Singleton* Egzemplarz(); protected: Singleton(); private: static Singleton* _egzemplarz; Zagwarantowanie unikatowego egzemplarza Implementacja Singleton* Singleton::_egzemplarz = 0; Singleton* Singleton::Egzemplarz() { if (_egzemplarz == 0) { _egzemplarz = new Singleton; return _egzemplarz; Tworzenie podklas klasy Singleton Uwaga To jedna z kilku metod. Wykorzystanie archiwum deklaracja 2
class Singleton { static void Wprowadz(const char* nazwa, Singleton*); static Singleton* Egzemplarz(); protected: static Singleton* Wyszukaj(const char* nazwa); private: static Singleton* _egzemplarz; static List<ParaNazwaSingleton>* _archiwum; Tworzenie podklas klasy Singleton Wykorzystanie archiwum implementacja Singleton* Singleton::Egzemplarz() { if (_egzemplarz == 0) { const char* nazwasingletonu = "MAGIA_DZIALA"; _egzemplarz = Wyszukaj(nazwaSingletonu); return _egzemplarz;... MojSingleton::MojSingleton() { //... Singleton::Wprowadz("MojSingleton", this)... static MojSingleton singleton; 3 Adapter 3.1 Denicja Adapter Przeznaczenie Wzorzec przeksztaªca interfejs klasy w taki, jakiego klienci oczekuj. Dzi ki Adapterowi klasy mog wspóªpracowa, co bez niego nie byªoby mo»liwe, poniewa» maj niezgodne interfejsy. Przykªad Doª czenie istniej cej rejestracji do grup do nowego modelu jej obsªugi. 3
Adapter stosowalno± Stosowalno± chcesz wykorzysta istniej c klas, a jej interfejs nie odpowiada temu, którego potrzebujesz; chcesz utworzy klas wielokrotnego u»ytku, która wspóªpracuje z niepowi zanymi ze sob lub nieprzewidzianymi klasami, to znaczy takimi, które niekoniecznie maj zgodne interfejsy; (tylko adapter obiektów) potrzebujesz u»y kilku istniej cych podklas, ale zaadaptowanie ich interfejsów przez tworzenie ich podklas jest niepraktyczne; adapter obiektów mo»e adaptowa interfejs swojej nadklasy. Struktura adaptera klas Struktura adaptera obiektów Konsekwencje adapterów Konsekwencje adaptera klas adaptuje Adaptowanego do Celu, ale nie b dzie dziaªaª na podklasy Adaptowanego; umo»liwia Adapterowi przedeniowanie cz ±ci zachowania Adaptowanego; 4
wprowadza tylko jeden obiekt, aby dosta si do Adaptowanego. Konsekwencje adaptera obiektów umo»liwia jednemu Adapterowi dziaªanie z wieloma Adaptowanymi, w tym z wszystkimi podklasami Adaptowanego; utrudnia przedeniowywanie zachowania Adaptowanego. 3.2 Implementacja Adapter klas deklaracja class Ksztalt{ Ksztalt(); virtual void RamkaBrzegowa( Punkt& lewydolny, Punkt& prawygorny); virtual Manipulator* StworzManipulator(); class WidokTekstu{ WidokTekstu(); void PodajPoczatek(Wspol& x, Wspol& y); void PodajRozmiar(Wspol& szerokosc, Wspol& wysokosc); virtual bool JestPusty(); Adapter klas deklaracja class KsztaltTekst : public Ksztalt, private WidokTekstu{ KsztaltTekst(); virtual void RamkaBrzegowa( Punkt& lewydolny, Punkt& prawygorny); virtual bool JestPusty(); virtual Manipulator* StworzManipulator(); Adapter klas implementacja 5
void KsztaltTekst::RamkaBrzegowa( Punkt& lewydolny, Punkt& prawygorny) { Wspol dol, lewo, szerokosc, wysokosc; PodajPoczatek(dol, lewo); PodajRozmiar(szerokoc, wysokosc); lewydolny = Punkt(dol, lewo); lewydolny = Punkt(dol+wysokosc, lewo+szerokosc); bool KsztaltTekst::JestPusty() { return WidokTekstu::JestPusty(); ; Manipulator* StworzManipulator() { return new ManipulatorTekstow(this); Adapter obiektu deklaracja class KsztaltTekst : public Ksztalt { KsztaltTekst(WidokTekstu * t) { _tekst = t; ; virtual void RamkaBrzegowa( Punkt& lewydolny, Punkt& prawygorny); virtual bool JestPusty(); virtual Manipulator* StworzManipulator(); private: WidokTekstu* _tekst; Adapter obiektu implementacja void KsztaltTekst::RamkaBrzegowa( Punkt& lewydolny, Punkt& prawygorny) { Wspol dol, lewo, szerokosc, wysokosc; _tekst->podajpoczatek(dol, lewo); _tekst->podajrozmiar(szerokoc, wysokosc); lewydolny = Punkt(dol, lewo); lewydolny = Punkt(dol+wysokosc, lewo+szerokosc); bool KsztaltTekst::JestPusty() { return _tekst->jestpusty(); ; Manipulator* StworzManipulator() { return new ManipulatorTekstow(this); 6
4 Kompozyt 4.1 Denicja Kompozyt Przeznaczenie Wzorzec ten skªada obiekty w struktury drzewiaste reprezentuj ce hierarchie typu cz ± -caªo±. Umo»liwia klientom jednakowe traktowanie pojedynczych obiektów i zªo»e«obiektów. Przykªad Struktura jednostek organizacyjnych w systemie Internetowej Rekrutacji Kandydatów na studia. Kompozyt stosowalno± Stosowalno± chcesz przedstawi hierarchie obiektów cz ± -caªo± ; chcesz, by klienci mogli ignorowa ró»nic mi dzy zªo»eniami obiektów, a pojedynczymi obiektami; klienci b d wtedy jednakowo traktowa wszystkie obiekty wyst puj ce w strukturze. Struktura kompozytu Konsekwencje kompozytu Konsekwencje kompozytu Deniuje hierarchie klas grupuj ce obiekty pierwotne i zªo»one. Upraszcza budow klienta. Uªatwia dodawanie nowych rodzajów komponentów. Mo»e sprawi,»e projekt b dzie zbyt ogólny. 7
4.2 Implementacja Kompozyt deklaracja class Sprzet{ virtual Pieniadze Cena(); protected: Sprzet(); class StacjaDyskietek : public Sprzet { virtual Pieniadze Cena() {return Pieniadze(10);; class KompozytSprzetowy : public Sprzet { virtual Pieniadze Cena(); protected: KompozytSprzetowy(); private: Lista<Sprzet *> _sprzet; Kompozyt implementacja Pieniadze KompozytSprzetowy::Cena() { Iterator<Sprzet*>* i = StworzIterator(); Pieniadze razem = 0; for (i->napoczatek();!i->zrobione(); i->nastepny()) { razem += i->biezacyelement->cena(); delete i; return razem; 5 Peªnomocnik 5.1 Denicja Peªnomocnik Przeznaczenie Wzorzec ten zapewnia substytut lub reprezentanta innego obiektu w celu sterowania dost pem do niego. Przykªad 8
Inicjalizowanie poª czenia do bazy danych. Stosowalno± Zawsze wtedy, kiedy potrzeba bardziej uniwersalnego lub bardziej wyranowanego odwoªania do obiektu, ni» zwykªy wska¹nik. Struktura peªnomocnika Konsekwencje peªnomocnika Konsekwencje peªnomocnika Peªnomocnik wprowadza dodatkowy poziom po±rednio±ci przy dost pie do obiektu. 5.2 Implementacja Peªnomocnik deklaracja class ObiektGraficzny { virtual void Rysuj() = 0; protected: ObiektGraficzny(); ; class Rysunek : public ObiektGraficzny { virtual void Rysuj(); Rysunek(char* z); ; class PelnomocnikRysunku : public ObiektGraficzny { virtual void Rysuj(); PelnomocnikRysunku(char* z); protected: Rysunek* PodajRysunek(); private: Rysunek* _rysunek; char* _nazwapliku; ; Peªnomocnik implementacja PelnomocnikRysunku::PelnomocnikRysunku(char* z) { _nazwapliku = strdup(z); 9
_rysunek = 0; Rysunek* PelnomocnikRysunku::PodajRysunek() { if (_rysunek == 0) { _rysunek = new Rysunek(_nazwaPliku); return _rysunek; void PelnomocnikRysunku::Rysuj() { PodajRysunek()->Rysuj() 10