Stáhnout prezentaci
Prezentace se nahrává, počkejte prosím
ZveřejnilRadomír Bláha
1
Prototyp
2
O čem to bude?
3
Prototyp Záměr vytváření objektů nový objekt se vytváří kopírováním (klonováním) vzoru – prototypu
4
Motivace – Grafický editor Obecný grafický editor Graphic obecný grafický objekt Tool umí cosi dělat s objekty Graphic třída GraphicTool produkuje komponenty Graphic Editor hudebních partitur noty, pomlky,... – podtřídy Graphic problém – jak pomocí GraphicTool vytvářet instance konkrétních tříd? GraphicTool je obecná!
5
Motivace – Řešení 1 – paralelní Creator třídy Návrh: Application specific classes Tool Manipulate() Staff Draw(Position) GraphicTool Manipulate() Graphic Draw(Position) GraphicToolStaff Manipulate() Nový potomek pro každou grafickou třídu Framework classes
6
Motivace – Řešení 2 - Generics Návrh class GraphicTool where T : Graphic, new() { public GraphicTool() { T g = new T(); //zobraz grafický objekt } Jsme omezeni na jeden způsob konstrukce
7
Motivace – Řešení 3 - Prototype Návrh: Elegantnější!!! Třídy aplikace Třídy frameworku
8
Prototyp – struktura Prototype: deklaruje rozhraní pro klonování ConcretePrototype: implementuje klonování Client: vytváří objekt zavoláním metody Clone() na prototype Client operation() Prototype clone() prototype ConcretePrototype1 clone() ConcretePrototype2 clone() Vrací svou kopii p = prototype.clone()
9
Prototyp – příklad struktury abstraktní třída (rozhraní) pro grafické objekty nástroj pro tvorbu objektů je parametrizovaný konkrétní instancí - prototypem abstraktní třída pro manipulaci s grafickými objekty
10
Prototyp – použití Kdy se nám hodí? nechceme duplikovat hierarchii tříd paralelní hierarchií továren jedna třída, několik málo stavů drahá konstrukce objektu Jak tyto problémy řeší? továrnu nepotřebujeme, kód pro vytváření je v Clone() místo vytváření třídy vyrobíme prototypickou instanci pro každý stav ke konstrukci dojde jen jednou, poté klonujeme
11
Prototyp – implementace Operace Clone „mělká vs. hluboká“ kopie Mělká kopie Hluboká kopie pozor na cyklické reference!! builtin podpora C++ copy konstruktor Java: Object.clone(), interface Cloneable = prototyp C#: object.MemberwiseClone(), ICloneable AB AClone AB BClone @Override public Object clone() throws CloneNotSupportedException { A aClone = (A)super.clone(); aClone.b = (B)b.clone(); return aClone; } Interně se nevolá konstruktor public object Clone() { { f.Serialize(this); var aClone =(A)f.Deserialize(); return aClone; }
12
Prototyp – implementace další parametry pro konstruktor? Clone() to neumí Initialize(...) pozor na deep copy a leaky Správce prototypů volitelně dynamický katalog, asociativní pole vyhledávání, registrace prototypů pro nějaký klíč
13
Prototyp – příklad implementace třída MazePrototypeFactory konstruktor MazePrototypeFactory přebírá prototypy jako argumenty ušetřili jsme tvorbu podtříd pro každý druh stěn nebo místností class MazePrototypeFactory : public MazeFactory { public: MazePrototypeFactory (Maze*, Wall*, Room*, Door*); virtual Maze* MakeMaze() const; virtual Room* MakeRoom(int) const; virtual Wall* MakeWall() const; virtual Door* MakeDoor(Room*, Room*) const; private: Maze* prototypeMaze_; Room* prototypeRoom_; Wall* prototypeWall_; Door* prototypeDoor_; }; MazePrototypeFactory:: MazePrototypeFactory ( Maze* m, Wall* w, Room* r, Door* d) { prototypeMaze_ = m; prototypeWall_ = w; prototypeRoom_ = r; prototypeDoor_ = d; }
14
Prototyp – příklad implementace jednoduché metody pro tvorbu (stěn, místností, dveří) klonují prototyp a potom ho inicializují bludiště vytvoříme pomocí MazePrototypeFactory inicializovanou prototypy základních komponent bludiště Wall* MazePrototypeFactory::MakeWall () const { return prototypeWall_->Clone(); } Door* MazePrototypeFactory:: MakeDoor (Room* r1, Room *r2) const { Door* door = prototypeDoor_->Clone(); door->Initialize(r1, r2); return door; } MazeGame game; MazePrototypeFactory simpleMazeFactory( new Maze, new Wall, new Room, new Door ); Maze* maze = game.CreateMaze(simpleMazeFactory);
15
Prototyp – příklad implementace změna typu bludiště – inicializovat MazePrototypeFactory pomocí jiné sady prototypů objekt, který chceme použít jako prototyp, např. instance Door, musí podporovat operaci Clone, případně operaci Initialize MazePrototypeFactory bombedMazeFactory( new Maze, new BombedWall, new RoomWithABomb, new Door); class Door : public MapSite { public: Door(); Door(const Door&); virtual void Initialize(Room*, Room*); virtual Door* Clone() const; virtual void Enter(); Room* OtherSideFrom(Room*); private: Room* room1_; Room* room2_; }; Door::Door (const Door& other) { room1_ = other.room1_; room2_ = other.room2_; } void Door::Initialize (Room* r1, Room* r2) { room1_ = r1; room2_ = r2; } Door* Door::Clone () const { return new Door(*this); }
16
Prototyp – příklad implementace podtřída BombedWall musí operaci Clone přetížit a implementovat příslušný kopírovací konstruktor klienti klonující prototyp neví o jeho konkrétní podtřídě např.: BombedWall::Clone() vrací Wall*, ale implementace vrací ukazatel na novou instanci podtřídy ( BombedWall* ) Skrývá podtřídu klientům class BombedWall : public Wall { public: BombedWall(); BombedWall(const BombedWall&); virtual Wall* Clone() const; bool HasBomb(); private: bool bomb_; }; BombedWall::BombedWall (const BombedWall& other) : Wall(other) { bomb_ = other.bomb_; } Wall* BombedWall::Clone () const { return new BombedWall(*this); }
17
Praktické využití: Cacheování dat
18
public interface IPrototype { IPrototype Clone(); } public class Configuration : IPrototype { private string fileInformation; public void GetFileInformation() { Thread.Sleep(5000); //Nahrazeni asynchronniho volani fileInformation = "Long file information"; } IPrototype IPrototype.Clone() { Configuration c = new Configuration(); c.fileInformation = this.fileInformation; return c; } public void ShowInformation() { Console.WriteLine("Showing " + fileInformation); }
19
Praktické využití: Cacheování dat public class PrototypeManager { private Dictionary list = newDictionary (); public void AddPrototype(IPrototype p, int index) { list.Add(index, p); } public IPrototype GetPrototype(int index) { return list[index].Clone(); }
20
Praktické využití: Cacheování dat static void Main(string[] args) { Configuration c = new Configuration(); c.GetFileInformation(); UserProfile up = new UserProfile(); up.GetDatabaseInformation(); PrototypeManager manager = new PrototypeManager(); manager.AddPrototype(c, 0); manager.AddPrototype(up, 1); (manager.GetPrototype(0).Clone() as Configuration).ShowInformation(); (manager.GetPrototype(1).Clone() as UserProfile).ShowData(); } Rychlé Pomalé
21
Porovnání s ostatními vzory Factory method Snadná na implementaci Není moc komplexní Vytváří nový objekt od začátku Abstract Factory, Builder Vysoce flexibilní Komplexní Oddělení objektu od jeho vytváření Vytváří nový objekt od začátku Prototype Vysoce flexibilní Komplexní Objekt a způsob jeho vytváření jsou specifikovány na stejném místě Kopíruje již existující objekt
22
Typické využití Nástroj pro grafické prvky Elektrické obvody Hudební software Šablony Pokud je vytváření instance drahé např: parsování XML dat pouze jednou Cacheování dat z databází Pokud instance třídy mají málo možných stavů katalog barev, fontů
23
Shrnutí - výhody Možnost vytvářet objekty bez znalosti konkrétních tříd Specifikace nových objektů změnou hodnoty (flexibilní chování) Snížení počtu podtříd Specifikace nových objektů změnou struktury (kompozice) Odstranění hierarchie továren Vytváření instancí = volání Clone() Implementace v prototypu – žádná jiná třída není ovlivněna.
24
Shrnutí - nevýhody Nutnost úpravy kódu, pokud třída neimplementuje metodu clone() Cyklické reference
Podobné prezentace
© 2024 SlidePlayer.cz Inc.
All rights reserved.