Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
1
Abstract Factory
2
Motivace (problém) Problém
programujeme grafickou knihovnu pro tvorbu aplikací požadavky přenositelnost nativní vzhled pro daný OS
3
Motivace (problém) Cíl Jak toho dosáhneme?
minimální duplikace kódu uživatele snadno přidat/odebrat/vyměnit objekt odstínit uživatele od implementace objektů Jak toho dosáhneme? Abstract Factory!
4
Motivace (problém) Řešení
Uživatel pracuje pouze s rozhraními (tj. GUIFactory, Button, TextBox) Řešení Rozhraní pro objekty Abstraktní továrna – určuje rozhraní konkrétních továren Konkrétní objekty –implementace vzhledu pro „Button“ Konkrétní továrny – implementují rozhraní abstraktní továrny Konkrétní objekty –implementace vzhledu pro „TextBox“
5
Důsledek Abstract Factory
Rozhraní AbstractFactory samo vynucuje závislosti mezi konkrétnimi objekty např.: tlačítko pro OSX můžeme použít pouze s text boxem pro OSX
6
Kdy použít Cheme nezávislost na tom, jak objekty tvoříme, skládáme a reprezentujeme Chceme vynutit, aby skupina souvisejících objektů byla používaná společně Chceme zpřístupnit pouze rozhraní objektů, ne implementaci
7
Implementace Programujeme hru jako je Doom
Dvě různé obtížnosti – dvě skupiny nepřátel Enemy Soldier Monster SuperMonster EasySoldier HardSoldier EasyMonster HardMonster EasySuperMonster HardSuperMonster Jedna úrověň – jedna skupina nepřátel (Easy/Hard) chceme vynutit – Abstract Factory!
8
Implementace Hlavní továrna class AbstractEnemyFactory { public:
virtual ~AbstractEnemyFactory() { } virtual Soldier* MakeSoldier() = 0; virtual Monster* MakeMonster() = 0; virtual SuperMonster* MakeSuperMonster() = 0; };
9
Implementace Konkrétní továrny pro každou skupina nepřátel (Easy, Hard) class EasyLevelEnemyFactory : public AbstractEnemyFactory { public: Soldier* MakeSoldier() { return new EasySoldier; } Monster* MakeMonster() { return new EasyMonster; } SuperMonster* MakeSuperMonster() { return new EasySuperMonster; } }; class HardLevelEnemyFactory : public AbstractEnemyFactory { public: Soldier* MakeSoldier() { return new HardSoldier; } Monster* MakeMonster() { return new HardMonster; } SuperMonster* MakeSuperMonster() { return new HardSuperMonster; } };
10
Implementace Rozhraní pro nepřátele class Soldier { public:
virtual ~Soldier() { } virtual void SoldierAttack() = 0; }; class Monster { public: virtual ~Monster() { } virtual void MonsterAttack() = 0; }; class SuperMonster { public: virtual ~SuperMonster() { } virtual void SuperMonsterAttack() = 0; };
11
Implementace Konkrétní nepřátele class EasySoldier : public Soldier {
void SoldierAttack() { /* Easy soldier attack */ } }; class EasyMonster : public Monster { public: void MonsterAttack() { /* Easy monster attack */ } }; class EasySuperMonster : public SuperMonster { public: void SuperMonsterAttack() { /* Easy super monster attack */ } };
12
Implementace Zvenčí class GameApp { ... void SelectLevel()
if (user chooses the Easy level) factory_ = new EasyLevelEnemyFactory; } else factory_ = new HardLevelEnemyFactory; private: AbstractEnemyFactory* factory_; };
13
Výhody Izolace konkrétních tříd
uživatel pracuje s abstraktním předkem jména konkrétních objektů se v uživatelově kódu neobjeví větší kontrola nad implementací Snadná změna skupin objektů (z pohledu uživatele) konkrétní továrna v kódu pouze jednou stačí vyměnit konkrétní továrnu Vynucuje konzistenci v rámci objektů chceme-li, aby skupina objektů fungovala pouze společně
14
Nevýhody Přidání nové skupiny objektů Přidání nových druhů objektů
nutno přidat celou novou konkrétní továrnu Přidání nových druhů objektů nutno upravit AbstractFactory a všechny konkrétní továrny Menší flexibilita konkrétní objekty mohou podporovat pouze průnik množin funkcí objektů
15
Přidání nových druhů objektů - řešení
Rozšiřitelná továrna Místo jednotlivých metod pro vytvoření každého objektu pouze jedna metoda – Make() Jaký objekt chceme vytvořit určíme přes parametr metody Lze použít pouze pokud všechny objekty mají stejného abstraktního předka! ztráta typové kontroly Nový druh objektu = změníme metodu Make()
16
Přidání nových druhů objektů - řešení
class AbstractEnemyFactory { public: virtual ~AbstractEnemyFactory() { } virtual Enemy* Make(EnemyType type) = 0; }; class EasyLevelEnemyFactory : public AbstractEnemyFactory { public: Enemy* Make(EnemyType type) { switch(type) { case SOLDIER: return new EasySoldier; case MONSTER: return new EasyMonster; case SUPER_MONSTER: return new EasySuperMonster; default: } };
17
Konkrétní použití Java AWT java.awt.toolkit Abstract Window Toolkit
každá AWT komponenta (Component) obsahuje odpovídající objekt daného systému (ComponentPeer) java.awt.toolkit AbstractFactory potomci vrací příslušné objekty daného systému (MS Windows, X Window) createMenu(), createButton(), ... getDefaultToolkit(), getToolkit()
18
Další použití Databáze Filesystémy Odlišné grafické prvky
různé databáze – MySQL, Oracle, XML, .... základní operace zůstavají stejné (SQL dotaz, connect, ...) uživatel komunikuje s databází přes továrnu Filesystémy různé filesystémy, odlišné implementace navenek jsou jejich operaci skoro identické open, write, close, makedir, ... Odlišné grafické prvky multiplatformní aplikace chceme nativní vzhled
19
Související vzory Factory Method Prototype Singleton
objekt AbstractFactory v sobě má tovární metody pro vytvoření každého objektu konkrétní továrny tyto metody předefinovávají Prototype místo konkrétních továren pro každou skupinu objektů jedna CloneFactory chceme nový objekt – klonujeme prototyp Singleton konkrétní továrna často existuje v celém programu pouze jednou
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.