Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Factory Method. Motivace – tisk Knihovna tiskne dokumenty do pdf File Open() Close() Print() PresentationWritingDrawing Knihovna tiskne obrázky do pdf.

Podobné prezentace


Prezentace na téma: "Factory Method. Motivace – tisk Knihovna tiskne dokumenty do pdf File Open() Close() Print() PresentationWritingDrawing Knihovna tiskne obrázky do pdf."— Transkript prezentace:

1 Factory Method

2 Motivace – tisk Knihovna tiskne dokumenty do pdf File Open() Close() Print() PresentationWritingDrawing Knihovna tiskne obrázky do pdf JPEGGIFBMPFile Open() Close() Print()

3 public class Printer { public File printToPDF(String path) { File file; file = new Presentation, Writing or Drawing? file.Load(); file.Print(); file.Close(); return file; } Motivace – tisk Jak získáme tu správnou třídu k instanciování? Jak implementovat metodu printToPDF? Rozhodujeme se na základě přípony souboru

4 public class Printer { public File printToPDF(String path) { File file; if(ext(path) == "ppt") file = new Presentation(path); else if(ext(path) == "doc") file = new Writing(path); else if(ext(path) == "drw") file = new Drawing(path); file.Load(); file.Print(); file.Close(); return file; } Rychlé řešení Komplikace  Tisk obrázků místo dokumentů  Možné duplicity kódu  Přidání nového typu dokumentu (např. Excel) Rozhodnutí přímo v těle metody Potřebuje metoda znát potomky třídy File? Co když přidáme novou třídu Excel?

5 public class Printer { public abstract File CreateFile(string path); public void printToPDF(String path) { File file = this.CreateFile(path); file.Load(); file.Print(); file.Close(); } Factory Method – řešení public class ImagePrinter : Printer { public override File CreateFile(string path) { if(ext(path) == "jpeg") return new Jpeg(path); else if(ext(path) == "gif") return new Gif(path); return null; } public class DocumentPrinter : Printer { public override File CreateFile(string path) { if(ext(path) == "ppt") return new Presentation(path); else if(ext(path) == "doc") return new Writing(path); return null; } Knihovna pro tisk dokumentů Knihovna pro tisk obrázků Výhoda - zapouzdření

6 public class Printer { public abstract File CreateFile(string path); public void printToPDF(String path) { File file = this.CreateFile(path); file.Load(); file.Print(); file.Close(); } Factory Method – řešení 2.0 public class ImagePrinter : Printer { public override File CreateFile(string path) { if(ext(path) == "jpeg") return new Jpeg(path); else if(ext(path) == "gif") return new Gif(path); return base.CreateFile(path); } public class DocumentPrinter : Printer { public override File CreateFile(string path) { if(ext(path) == "ppt") return new Presentation(path); else if(ext(path) == "doc") return new Writing(path); return base.CreateFile(path); } Knihovna pro tisk dokumentů Knihovna pro tisk obrázků

7 Motivace 2 – hra public class Game { public Room GenerateRoom() { Room room = new Room(); room.add(new Door()); int monsters = random(0,5); for(int i = 0; i < monsters; ++i) { room.add(new Monster()); } Metoda generuje místnosti ve hře Chceme přidat novou třídu AdvancedMonster  Jak ji integrovat do hry?

8 Factory Method – řešení public class Game { public virtual Room CreateRoom() { return new Room(); } public virtual Door CreateDoor() { return new Door(); } public virtual Monster CreateMonster() { return new Monster(); } public Room GenerateRoom() { Room room = this.CreateRoom(); room.add(this.CreateDoor()); int monsters = random(0,5); for(int i = 0; i < monsters; ++i) { room.add(this.CreateMonster()); } return room; } Delegujeme instanciování na dedikované metody public class HardGame : Game { public override Monster CreateMonster() { return new AdvancedMonster(); }

9 Struktura Účastníci  Product ( File ) definuje rozhraní objektů vytvářených tovární metodou  ConcreteProduct ( Presentation ) implementuje rozhraní Productu  Creator ( Printer ) deklaruje tovární metodu vracející objekt typu Product může definovat defaultní implementaci vracející defaultní objekt ConcreteProduct  ConcreteCreator ( DocumentPrinter ) implementuje tovární metodu vracející instanci ConcreteProductu Factory Method – struktura

10 Factory Method – přehled Známý jako  Tovární metoda nebo Virtual Constructor Kategorie  Creational design patterns Účel  Definuje rozhraní pro vytvoření objektu  Odložení instanciace na potomka  Potomci sami rozhodují, kterou třídu instanciovat Obecné podmínky  Třída nezná konkrétní potomky  Delegace instanciace na jedno místo + zapouzdření  Potřeba lifetime managementu na centrálním místě Praktické situace  Framework pro více využití => Document, Image  Nahrazení využívaných tříd jejich potomky => AdvancedMonster  Rozšíření aplikace o nové třídy => Excel, HillSlotCarPiece  Testování

11 Propojení paralelních hierarchií tříd  třída deleguje některé akce na jinou třídu  příklad: manipulovatelné grafické objekty (úsečka, obdélník,...) stav manipulace udržován pouze během manipulace - ne u grafického objektu manipulace různých objektů uchovávají různý stav (koncový bod, rozteč řádků,...) objekt Manipulator, konkrétní grafické objekty mají vlastní manipulátory Figure deklaruje CreateManipulator, potomci vytvářejí vlastní manipulátory částečně paralelní hierarchie - dědění defaultního manipulátoru Factory Method – paralelní hierarchie

12 Factory Method – static factory method public class Complex { public double real; public double imaginary; public static Complex FromCartesian(double real, double imaginary) { return new Complex(real, imaginary); } public static Complex FromPolar(double modulus, double angle) { return new Complex(modulus * Cos(angle), modulus * Sin(angle)); } private Complex(double real, double imaginary) { this.real = real; this.imaginary = imaginary; } Když už není možné přetížit konstruktory Nevýhody  Bez privátních nebo protected konstruktorů nelze vytvářet potomky Creatora Výhody  Není nutné vždy vytvářet novou instanci  Lze vracet jakéhokoliv potomka

13 Factory Method – testování Komunikační framework  třída Client  potomek DangerousClient Automatické testování bezpečnosti  potřeba automaticky podstrčit třídu DangerousClient Řešení  vzor Factory Method pro třídu Client

14 Factory Method – implementace Implementace  dvě hlavní varianty Creator je abstraktní třída (nebo interface)  nutnost dědičnosti a vlastní implementace Creator je standardní třída => defaultní implementace  flexibilita  parametrizované tovární metody variace - více druhů produktů metoda dostane parametr identifikující druh objektu (ProdId) všechny objekty sdílejí jedno rozhraní - Product class Creator { public: virtual Prod* Create(ProdId); }; Prod* Creator::Create (ProdId id) { if(id==MINE) return new MyProd; if(id==YOURS) return new YourProd; return 0; } Prod* MyCreator::Create (ProdId id) { if(id==MINE) return new MyProd2; if(id==THEIRS) return new TheirProd; return Creator::Create(id); } Obsluha ostatních id se deleguje na předka

15 Factory Method – implementace  použití šablon někdy zbytečné vytvářet další potomky šablona parametrizovaná Produktem není zapotřebí vytvářet potomky class Creator { public: virtual Product* CreateProduct() = 0; }; template class StdCreator: public Creator { public: virtual Product* CreateProduct(); }; template Product* StdCreator ::CreateProduct() { return new T; } class MyProduct : public Product { public: MyProduct(); //... }; StdCreator myCreator; vrací konkrétního potomka abstraktního produktu

16 Factory Method – příklady použití virtual Qmenu* QmainWindow::createPopupMenu() Qt gui framework (C++) Java API – XML parsery, DateFormat třída  DocumentBuilderFactory, DocumentBuilder  SAXParserFactory, SAXParser Zend webový aplikační framework (PHP)  Třída Zend_Db – connector k různým typům databází // require_once 'Zend/Db/Adapter/Pdo/Mysql.php'; // Automatically load class Zend_Db_Adapter_Pdo_Mysql // and create an instance of it. $db = Zend_Db::factory('Pdo_Mysql', array( 'host' => '127.0.0.1', 'username' => 'webuser', 'password' => 'xxxxxxxx', 'dbname' => 'test' )); Factory method Pdo_Sqlite, Pdo_Mssql, Oracle, DB2,... DateFormat df1 = DateFormat.getDateInstance(DateFormat.FULL, Locale.FRANCE); Factory method

17 Factory Method – příklady použití public static function factory($adapter, $config = array()) { // obtaining adapter class name $adapterName = strtolower($adapterNamespace. '_'. $adapter); // Load the adapter class. This throws an exception // if the specified class cannot be loaded. @Zend_Loader::loadClass($adapterName); // Create an instance of the adapter class. // Pass the config to the adapter class constructor. $dbAdapter = new $adapterName($config); // Verify that the object created is // a descendent of the abstract adapter type. if (! $dbAdapter instanceof Zend_Db_Adapter_Abstract) { // throwing Zend_Db_Exception require_once 'Zend/Db/Exception.php'; throw new Zend_Db_Exception("Adapter class '$adapterName' does not “ “extend Zend_Db_Adapter_Abstract"); } return $dbAdapter; } Factory method Concrete Product test of Product base class

18 Factory Method – výhody a nevýhody Výhody  Oddělení vrstev Odstraní nutnost používat aplikačně-specifické třídy Možnost definovat vlastní ConcreteProduct  Propojení paralelních tříd Jasně určí, které třídy patří k sobě Nevýhody  Nutnost vytvořit potomka Vytváření potomka Creator pouze kvůli instanci ConcreteProduct Nevadí pokud klient musí vždy vytvořit potomka

19 Factory Method - související návrhové vzory Shrnutí  flexibilita za relativně malou cenu  obvyklá základní metoda zvýšení flexibility virtual constructor  časté využití jinými vzory Abstract Factory  často implementovaná pomocí továrních metod Template Method  často volány tovární metody Prototype  nevyžaduje dědění Creatora ... avšak vyžaduje navíc inicializaci produktové třídy (např. Clone())


Stáhnout ppt "Factory Method. Motivace – tisk Knihovna tiskne dokumenty do pdf File Open() Close() Print() PresentationWritingDrawing Knihovna tiskne obrázky do pdf."

Podobné prezentace


Reklamy Google