Design Patterns
A Tervezési minták: az újrahasználható objektumorientált szoftver elemei (eredeti címén angolul Design Patterns: Elements of Reusable Object-Oriented Software) egy 1994-es szoftverfejlesztési könyv, amelyben programtervezési minták vannak részletesen leírva. A könyvet Erich Gamma, Richard Helm, Ralph Johnson, és John Vlissides írta, a hozzátartozó előszót pedig Grady Booch. A szerzőket szokás Gang of Four (GoF), azaz Négyek bandája néven együtt említeni. A könyv két részből áll: az első két fejezet az objektumorientált programozás által nyújtott lehetőségekről és a felmerülő buktatókról szól, a maradék fejezetekben pedig 23 klasszikus tervezési mintát mutatnak be. A könyv C++ és Smalltalk nyelven tartalmaz példákat. A könyvnek nagy jelentősége van a szoftverfejlesztés területén, és fontos forrásként tekinthetünk rá az objektumorientált tervezés elméleti és gyakorlati alkalmazásának vonatkozásában is. Több mint 500 000 példányt adtak már el angol és 13 másik nyelven. TörténeteA könyv egy birds of feather (BoF) beszélgetésben merült fel először a OOPSLA (Object-Oriented Programming, Systems, Languages & Applications) konferencián a 90-es években "Towards an Architecture Handbook" címmel Bruce Anderson vezetésével. Itt találkozott Erich Gamma és Richard Helm, akik felismerték, hogy mindkettőjüket érdeklik a tervezési minták. Később csatlakozott hozzájuk Ralph Johnson és John Vlissides[1] is. A könyv hivatalos kiadásának dátuma 1994. október 21., de a szerzői joga 1995-ös, ennélfogva gyakran 1995-ös kiadásként utalnak rá, habár a tényleges publikálása 1994-ben volt. A nyilvánosság számára a könyv az 1994-es októberi OOPSLA konferencián lett elérhető Portlandben. 2005-ben az ACM SIGPLAN a Programming Languages Achievement Award díjat adta az íróknak, a „programozási gyakorlaton és a programozási nyelvek tervezésére”[2] tett nagy hatása miatt. 2012 márciusában a könyvnek már 40. nyomtatásánál tartottak. Bevezetés, első fejezetAz első fejezete egy beszélgetés az objektumorientált tervezési technikákról az írók tapasztalatai alapján, olyanokról amik használatáról azt mondják, hogy egy jó objektumorientált szoftverdesign-t eredményez. Például:
Az írók szerint az interfészre programozás előnye az implementációra való programozással szemben a következők:
Az interfész használata dinamikus kötéseket és többalakúságot eredményez, amik az objektumorientáltság alapjai. A szerzők az öröklődésre fehér dobozos újrafelhasználásként utalnak, ahol a fehérdobozosság a láthatóságra utal, mert a szülő osztályok felépítése gyakran látható a leszármazott osztályok számára. Ezzel ellentétben az objektum összetételre feketedobozos újrafelhasználásként utalnak, mert belső információknak nem kell láthatóaknak lenniük, akkor sem, ha használjuk az objektumokat. Az írók beszélnek az öröklődés és az egységbe zárás közötti feszültségről, és azt állítják, hogy tapasztalatuk szerint a tervezők túl sokat használják az öröklést. (Gang of Four 1995:20). Ennek veszélyeit ilyen módon fogalmazzák meg:
Figyelmeztetnek, hogy egy alosztály implementálása annyira függővé válhat a szülőosztály implementációjától, hogy bármilyen változtatás a szülő implementációjában azt eredményez, hogy muszáj az alosztályt is módosítani. Ezenkívül, elmondják, hogy ezek elkerülésére egy lehetőség, hogy csak absztrakt osztályokból van öröklődés, ugyanakkor kiemelik, hogy ennél a megoldásnál minimális kódújrafelhasználás van. Az öröklődés használata főleg akkor javasolt, ha már létező komponensekhez új funkciót adunk, nagy részben a régi kód újrafelhasználásával és relatíve kevés új kód írásával. A szerzők a 'delegálás'-ra az objektum összetétel egy extrém formájaként tekintenek, ami mindig használható az öröklődés helyett. A delegálás 2 objektumból áll: A 'küldő' átadja saját magát a 'delegáló'-nak, hogy az rá tudjon hivatkozni. Így a link a 2 rész között csak a futási időben jön létre, nem a fordítási időben. A szerzők szintén beszélnek az úgynevezett paraméteres típusokról. Ezek megengedik bármilyen típus definiálását, anélkül, hogy specifikálni kellene a többi típust, amit használ. A nem specifikált típusok a 'paraméterek' a használat szempontjából. A szerzők elismerik, hogy a delegálás és a paraméterezés is nagyon erőteljes módszerek, de figyelmeztetnek is:
A szerzők továbbá különbséget tesznek az 'Aggregáció' (ahol az objektumnak 'van egy' vagy 'része egy' másik objektumnak, tehát a mindkét objektumnak ugyanakkora az élettartalma) és az egyszerű 'ismeretség' között (ahol az objektum csupán 'tud' a másik objektum létezéséről). Ez utóbbit szokták 'asszociációnak' vagy 'használói' kapcsolatnak is nevezni. Az ismeretség esetén az objektumok kérhetnek egyes műveleteket egymáshoz, de nem felelősek egymásért. Az ismeretség egy lazább kapcsolat, mint az aggregáció, és egy sokkal lazább összekötést igényel az objektumok között, ami gyakran fontos lehet a lehető legjobb karbantarthatóság szempontjából. A szerzők a 'toolkit', azaz eszközkészlet fogalmát használják, míg mások manapság talán inkább a 'class library', azaz osztály könyvtár kifejezést használják, mint például C++-ban vagy Javában. Az ő értelmezésükben az eszköztár az objektumorientált megfelelője a szubrutinkönyvtáraknak, ahol a szoftverkeretrendszer együttműködő osztályok egysége, amik újrahasználható design-t biztosítanak a szoftver egy specifikus osztálya számára. A szerzők elmondják, hogy egy alkalmazás fejlesztése nehéz, egy eszköztáré még nehezebb, a legnehezebb pedig a keretrendszer fejlesztése. Második fejezet: esettanulmányA második fejezet egy lépésről lépésre levezetett esettanulmánya egy WYSIWYG dokumentumszerkesztőnek, a Lexinek. A fejezet hét problémán megy végig, amiket sorban meg kell vizsgálni a helyes design-hoz Lexi esetén, beleértve minden megkötést is amiket követni kell. Minden probléma mélységeiben meg van vizsgálva és megoldási javaslatokat is adnak. Minden megoldás részletesen be van mutatva, beleértve a pszeudokódokat, valamint Objektummodellezési technikákat, ahol szükséges. Végül pedig, minden megoldáshoz hozzátársít egy vagy több tervezési mintát. Bemutatják, hogy a megoldás milyen formában implementálja az adott tervezési mintát. A hét probléma (beleértve a megkötéseket is) és a megoldások (beleértve a tervezési mintára/mintákra való hivatkozásokat) a következők: A dokumentum szerkezeteA dokumentum "alapvető grafikai elemek elrendezése", mint a karakterek, sorok stb., amik "egybefoglalják a dokumentum információ tartalmát". A dokumentum szerkezete ezeknek az elemeknek az összessége és minden elem visszavezethető más résszerkezetekre. Problémák és megszorítások
Megoldás és tervezési minta A rekurzív kompozíció, elemek egy hierarchikus szerkezete, ami "fokozatosan egyre komplexebb elemeket épít az egyszerűbbekből". Minden csomópont a szerkezetben tud a szülő és a gyerek elemeiről. Ha egy művelet elvégzése az egész szerkezeten történik, akkor minden csomópont meghívja a műveletet a saját gyerekein. (rekurzívan). Ez az összetétel tervezési mintának egy implementálása, ami csomópontoknak az összessége. A csomópont egy absztrakt alap osztály, és a tőle származhatnak levelek (egy esetén), vagy újabb csomópontokból álló kollekció(amik csomópontjai megint csak tartalmazhatnak leveleket, vagy újabb csomópont-kollekciókat). Amikor egy műveletet végrehajtanak egy szülőn, akkor a művelet rekurzív módon tovább adódik a hierarchián lefelé haladva. FormázásA formázás nem a szerkezetet jelenti. A formázás egy módszer egy adott rész felépítésére a dokumentum fizikai struktúrája szempontjából. Ide tartozik a szöveg sorokba törése, a kötőjelek használata, a margó szélesség beállítása stb. Problémák és megszorítások
Megoldás és tervezési minta Egy Compositor osztály egységbe fogja zárni az algoritmust ami az elrendezést szolgálja. A Compositor egy alosztálya az objektumnak a dokumentum szerkezetében. Egy Compositornak van egy társított példánya a Composition objektumból. Amikor a Compositor futattja a A Compositor maga egy absztrakt osztály, ami lehetővé teszik az őt származtató osztályoknak a különböző formázó algoritmusok használatát (mint például a szélesebb margók, dubla-spacek stb.) A stratégia programtervezési minta használható erre a célra. A stratégia egy módszer több algoritmus egységbe zárására a körülmények változására alapozva. Ebben az esetben a formázásnak különbözőnek kell lennie, attól függően, hogy szöveg, grafika, egyszerű elem stb. van-e formázva. Felhasználói felület kezeléseAnnak a felhasználói felületnek (user interface) a változtatása, amin keresztül a felhasználók kapcsolatba léphetnek a dokumentummal. Problémák és megszorítások
Megoldás és tervezési minta Az „átlátszó elkerítés” (transparent enclosure) segíti javítani az összetételekhez adott viselkedéseket. Az ilyen elemek, mint a szegélyek és a görgetősávok, speciális alosztályai egy-egy különálló elemnek. Mivel ezek a kiegészítések részei a struktúrának, így a megfelelő Ezt egy Díszítő tervezési minta, amely lehetővé teszi adott objektumokhoz más viselkedések hozzáadását, anélkül, hogy magát az objektumot módosítaná. Többféle "Look-And-Feel" szabvány támogatásaA "Look-And-Feel" kifejezés a platform-specifikus UI szabványokra utal. Ezek a szabványok "meghatározzák az iránymutatásokat arra vonatkozóan, hogy egy alkalmazás, hogyan jelenik meg és hogyan viselkedik a felhasználóval" Problémák és megszorítások
Megoldás és tervezési minta Mivel az objektum létrehozása a konkrét objektumok esetén nem történhet futási időben, így az objektum létrehozásának folyamatát el kell vonatkoztatni. Ez egy absztrakt guiFactory-val tehető meg, ami átveszi a UI elemek létrehozásának feladatkörét. Az abstract guiFactory-nak vannak konkrét implementációi, mint a MotifFactory, ami létrehozza a konkrét elemeit az ennek megfelelő típusnak (MotifScrollBar). Ilyen módon a programnak elég a ScrollBar-t kérnie, és futási időben ez megkapja a megfelelő konkrét elemet. Ez egy absztrakt gyár tervezési minta. Az átlagos gyár konkrét objektumot hoz létre egy típushoz. Az absztrakt gyár is konkrét objektumot hoz létre, de változó típusokhoz, a gyár konkrét implementációjától függően. Ez lehetővé teszi, hogy ne csak egyetlen konkrét objektumra fókuszáljunk, hanem egész konkrét objektum "családokra", "ezzel különbözik a többi létrehozási tervezési mintától, amik csak egyfajta termékobjektumot tartalmazhatnak" Több ablakos rendszerek támogatásaAhogyan a "look-and-feel" is különbözik platformonként, úgy az ablakok kezelésének művelete is. Minden platform máshogy jeleníti meg, kezeli az input és output formokat és rétegzi az ablakokat. Problémák és megszorítások
Megoldás és tervezési minta Lehetséges, hogy kifejlesszük a "saját, absztrakt és konkrét termékosztályainkat", mivel "minden ablakrendszer ugyanazt a dolgot csinálja általánosságban". Minden ablakrendszer műveleteket biztosít primitív alakzatok kirajzolására, átméretezésre, az ablak tartalmának frissítésére. Egy absztrakt alap Hogy elkerüljük a platform-specifikus Window alosztály létrehozásának szükségességét minden lehetséges platformra, egy interfészt fogunk használni. A Ez egy híd programtervezési minta. A Felhasználói műveletekMinden tevékenység amit a felhasználó a dokumentum kapcsán tehet, a szöveg beviteltől, a formázáson át a mentésig. Problémák és megszorítások
Megoldás és tervezési minta Minden menü elem, ahelyett, hogy paraméterlistával lenne szemléltetve, Command objektumokkal van megvalósítva. A Command egy absztrakt objektum, aminek csak egyetlen absztrakt metódusa van az A visszavonás és a mégis visszaállítás műveletének támogatására a Minden végrehajtott Ez a Helyesírás-ellenőrzés és elválasztásEz a dokumentumszerkesztő azon képessége, amivel szöveges szempontból vizsgálni tudja a dokumentum tartalmát. Bár sokféle vizsgálat elvégezhető, a fókuszban a helyesírás-ellenőrzés és az elválasztás (kötőjelezés) van. Problémák és megszorítások
Megoldás és tervezési minta A szám alapú indexelés eltávolítása az alapvető elemek esetén lehetővé teszi, hogy egy másfajta iterációs interfészt implementáljunk. Ez plusz metódusokat igényel a bejárásra és az objektum visszakeresésére. Ezek a metódusok egy abstract A bejárás és a visszakeresés függvényei az absztrakt Iterator interfészben vannak. A jövőbeli Iteratorok az alapján vannak származtatva, hogy milyen típusú listán kell majd végig iterálniuk, mint például tömbök (arrays) vagy láncolt listák (linked lists). Így függetlenül attól, hogy milyen módon történt az indexelés az elem használatának implementációjakor, a megfelelő Iteratort fogja használni. Ez az Iterátor programtervezési minta implementációja. Ez lehetővé teszi a kliensnek, hogy bejárjon egy objektumkollekciót, anélkül, hogy direkt módon hozzá kellene férnie, vagy azon kellene aggódnia hogy milyen fajta listaszerkezetet használ a kollekció. Most, hogy a bejárást már kezeltük, már lehetséges, hogy megvizsgáljuk az elem szerkezetét. Hogy minden elem szerkezetébe beépítsünk egyesével valamilyen vizsgálatot, az nem járható út, hiszen akkor minden elemben külön kellene a kód, pedig sok kód nagyon hasonló lenne a hasonló elemeknél. Ehelyett, egy generikus Így, hogy helyesírás ellenőrzést végezzünk, egy elejétől a végéig iterálónak kell hivatkozásként átadni a Ennél a módszernél, bármelyik algoritmus használható a bejárás metódusával, kemény kódolva az egyiket a másikkal. Például, a Find (Keresés) használható mint "find next" (következő keresése) vagy mint "find previous" (előző keresése), attól függően hogy a "forward" (előre) vagy "backward" (visszafelé) iterátor volt használva. Tehát összegezve, maguk az algoritmusok felelhetnek a különböző elemek kezeléséért. Például, egy Tervezési alapelvekA könyvben két tervezési alapelv jelenik meg, a GOF1 és a GOF2. Minták típusok szerintLétrehozásiA Létrehozási minták objektumok létrehozását valósítják meg, miközben javítják abban a rugalmasságot, hogy ki, hol, hogyan és mikor hozzon létre objektumokat.
SzerkezetiEzek az osztályok és objektumok elrendezésével kapcsolatosak, Öröklődést használnak, hogy összeállítsák az interfészeket és, hogy meghatározzanak különböző módokat az objektumok összetételére, hogy hogy adhatunk hozzájuk új funkcionalitást.
ViselkedésiA legtöbb ilyen tervezési minta az objektumok közötti kommunikációval kapcsolatos.
KritikaA szoftverfejlesztési tervezési minták koncepciójával szemben és a Design Patterns könyv kapcsán is fogalmaztak meg kritikákat. Az elsődleges kritika ami a Design Patternst érte, az volt, hogy a mintái egyszerűen csak a C++ hiányzó feature-eire adnak valamiféle megoldást az elegáns absztrakt feature-ök hosszú, koncentrált mintákra cserélésével. A kritikusok szerint lényegében arról van szó, hogy "emberi fordítóprogram"-ok lesznek vagy „néhány makro kézileg generált kibővítései” ezek. Peter Norvig rámutat, hogy 16 minta a 23-ból a könyveben egyszerűsödött vagy teljesen megszűnt Lisp-ben vagy Dylan-ben. Ehhez kapcsolódó megfigyeléseket tett Hannemann és Gregor Kiczales, akik többet mintát is implementáltak a 23-ból aspektusorientált programozási nyelven, az AspectJ használatával és megmutatták hogy a kód szintű függőségeket sikerült eltávolítani 17 minta esetén a 23-ból. Valamint, hogy az aspektusorientált programozás használatával egyszerűsíteni tudták a tervezési minták implementációját.[3] Ezen kívül humoros kritikák is születtek, mint például az OOPSLA-ban 1999. november 3-án,[4][5] és egy paródia is, Jim Coplientől ilyen címmel: "Kansas City Air Conditioner". Egy interjúban az InformIttal 2009-ben Erich Gamma elmondta, hogy a könyv szerzőinek 2005-ben volt egy beszélgetése arról, hogy változtatnának ma a könyvön. Arra jutottak, hogy valószínűleg újra kategorizálnának néhány mintákat, valamint hozzáadnának még néhány további mintát. Gamma eltávolította volna az Egyke (Singleton) mintát, de ebben nem jutottak közös nevezőre a szerzők.[6] Jegyzetek
|