Megint a Factory-ból kell kiindulni ám ezúttal prototípusokat lehet gyártani. A cél, hogy előre inicializált típusokat lehessen menet közben készíteni úgy, hogy annak részletkérdéseivel már ne kelljen foglalkozni. A típusokat klónozással kell előállítani, szükség esetén mély másolással. (Amikor a referencia tagokat újra kell kreálni, hogy két objektum ne használja őket közösen). Sokszor előfordul az, hogy bizonyos osztályt prototípusként használunk fel. Ilyenkor általában az "új" típust származtatjuk a régiből és semmit sem változtatunk rajta, csak a konstruktorban inicializáljuk:
class MyObject
{
int size;
public MyObject(int size)
{
this.size = size;
}
}
class MyOtherObject : MyObject
{
public MyOtherObject()
: base(22)
{ }
}
Ezzel tulajdonképpen semmit sem csináltunk, nem fejlesztettük tovább az objektumot, csak létrehoztunk egy prototípus osztályt. Ez főleg akkor válik nehézkessé, amikor ebből kellene 30-40 féle. Többek között az ilyen esetekre jó a Prototípus használata.
Alkalmazhatóság
Akkor használjuk a Prototype mintát, ha rendszernek függetlennek kell lennie a termék létrehozási, összeállítási és megjelenítési módjától; és
- ha a példányosítandó osztályok futásidőben határozódnak meg, például dinamikus betöltés esetén, vagy
- el szeretnénk kerülni a termékek osztályhierarchiájával párhuzamos osztályhierarchiájú gyárak építését, vagy
- amikor az osztályok példányainak csak néhány különböző állapotkombinációja lehet. Kényelmesebb a megfelelő számú prototípust elhelyezni és klónozni, mint példányosítani a megfelelő állapottal.
Struktúra
Résztvevők
A kliens megkéri a a prototípust, hogy klónozza önmagát.
A Prototype minta további előnyei:
A Prototype implementációjánál tartsuk szem előtt a következőket:
Résztvevők
- Protype: deklarál egy interface-t önmaga klónozásához.
- ConcretePrototype: implementál egy műveletet önmaga klónozásához.
- Client: új objektumot hoz létre, megkérve a prototípust önmaga klónozására.
Együttműködési információk
A kliens megkéri a a prototípust, hogy klónozza önmagát.
Következmények
A Prototype minta hasonló következményekkel jár mit az Abstract Factory és Builder: elrejti a termék osztályokat a kliens elől, csökkentve a ezzel azon nevek számát, amiket a kliens ismer. Emellett, ezek a minták lehetővé teszik, hogy a kliens módosítás nélkül dolgozzon az alkalmazás-specifikus osztályokkal.
A Prototype minta további előnyei:
- Termékek hozzáadása és eltávolítása futásidőben. Új konkrét termékosztály beépítése a rendszerbe, egyszerűen a prototípuspéldány bejegyeztetése a klienssel. Ez valamelyest hatékonyabb, mint a többi létrehozási minta, mert a kliens futásidőben építhet be és távolíthat el prototípusokat.
- Új objektumok meghatározása változó értékek mellett. A nagymértékben dinamikus rendszerek lehetővé teszik a új viselkedés definiálását az objektum összetételén keresztül – például az objektum változóinak értéket adva – és nem új osztályokat meghatározva. Ténylegesen a meglévő osztályok példányosításával, és ezek a prototípus kliens-objektumaiként bejegyeztetve adjuk meg. A kliens az új viselkedésmódot a felelősség prototípusra való átruházásával adhatja meg. Ez a tervezési mód lehetőséget ad új „osztályok” létrehozására programozás nélkül. Valójában a prototípus klónozása hasonló egy osztály példányosításához. A Prototype minta nagymértékben csökkenti a rendszer számára szükséges osztályok számát.
- Új objektum megadása változó struktúra mellett. Sok alkalmazás részekből és alrészekből építi fel az objektumokat. Kényelmi szempontok miatt, az ilyen alkalmazások lehetővé teszik az összetett, felhasználó által definiált struktúrák példányosítását.
- Kevesebb alosztály. A Prototype minta lehetőséget ad a prototípus klónozására, ahelyett, hogy egy gyártó metódust kérne meg új objektum létrehozására. Ezért nincs szükség Creator osztály hierarchiára.
- Alkalmazás dinamikus beállítása osztályokkal. Egyes futásidejű környezetek lehetővé teszik az osztályok dinamikus betöltését alkalmazásokba.
Implementációs rész
A Prototype implementációjánál tartsuk szem előtt a következőket:
- Prototype menedzser használata. Amikor egy rendszerben a prototípusok száma nem rögzített (tehát dinamikusan létrehozhatóak és megsemmisíthetőek), nyilván kell tartani a rendelkezésre álló prototípusokat. A kliensek maguk nem kezelik a prototípusokat, csak mentik és kiolvassák a nyilvántartóból. Egy kliens elkéri a prototípust a nyilvántartóból, mielőtt klónozná azt. Ezt nyilvántartót hívjuk Prototype menedzsernek. A prototype menedzser egy asszociatív tároló, ami egy adott kulcshoz tartozó prototípust ad vissza. Vannak műveletei a kulcshoz tartozó prototípus bejegyzésére és a bejegyzés érvénytelenítésére. A kliensek megváltoztathatják a nyilvántartót és tallózhatják azt futásidőben. Ez lehetővé teszi a klienseknek, hogy a rendszer leltárát kódírás nélkül felvegyék.
- A Clone művelet implementálása. A Prototype minta legnehezebb része a Clone művelet helyes implementálása. Ez kiváltképp bonyolult amikor az objektumstruktúra körkörös hivatkozásokat tartalmaz. Ha a rendszerben lévő objektumok rendelkeznek Save és Load műveletekkel, akkor ezek használhatóak a Clone alapértelmezett implementálásához, egyszerűen csak menteni kell az objektumot majd azonnal visszatölteni. A Save művelet menti az objektumot egy puffermemóriába, a Load egy másolatot hoz létre, rekonstruálva a objektumot a pufferből.
- Klónok inicializálása. Amíg néhány kliens tökéletesen elégedett a klónnal, ahogy van, mások az általuk választott értékkel akarják inicializálni néhány vagy az összes belső állapotát. Általában ezeket az értékeket nem lehet átadni a Clone műveletben, mert számuk prototípus-osztályonként változik. Néhány prototípusnak szüksége lehet több inicializáló paraméterre; másoknak egyre sincs szükségük. A Clone műveletben történő paraméterátadás eleve kizárná egy egységes klónozó interfész használatát. Lehetséges, hogy a prototípus osztályok már definiálnak műveleteket az állapot kulcsrészeinek (újra) beállítására. Ha ez van, akkor a kliensek ezeket a műveleteket használhatják azonnal klónozás után. Ha nincs, akkor lehet nekünk kell az Initialize műveletet bevezetni, amely argumentumként kapja meg az inicializáló paramétereket és ennek megfelelően állítja be a klón belső állapotát.
Minta kód
// Prototype pattern
using System;
using System.Collections.Generic;
namespace Prototype
{
///
/// MainApp startup class for Real-World
/// Prototype Design Pattern.
///
class MainApp
{
///
/// Entry point into console application.
///
static void Main()
{
ColorManager colormanager = new ColorManager();
// Initialize with standard colors
colormanager["red"] = new Color(255, 0, 0);
colormanager["green"] = new Color(0, 255, 0);
colormanager["blue"] = new Color(0, 0, 255);
// User adds personalized colors
colormanager["angry"] = new Color(255, 54, 0);
colormanager["peace"] = new Color(128, 211, 128);
colormanager["flame"] = new Color(211, 34, 20);
// User clones selected colors
Color color1 = colormanager["red"].Clone() as Color;
Color color2 = colormanager["peace"].Clone() as Color;
Color color3 = colormanager["flame"].Clone() as Color;
// Wait for user
Console.ReadKey();
}
}
///
/// The 'Prototype' abstract class
///
abstract class ColorPrototype
{
public abstract ColorPrototype Clone();
}
///
/// The 'ConcretePrototype' class
///
class Color : ColorPrototype
{
private int _red;
private int _green;
private int _blue;
// Constructor
public Color(int red, int green, int blue)
{
this._red = red;
this._green = green;
this._blue = blue;
}
// Create a shallow copy
public override ColorPrototype Clone()
{
Console.WriteLine(
"Cloning color RGB: {0,3},{1,3},{2,3}", _red, _green, _blue);
return this.MemberwiseClone() as ColorPrototype;
}
}
///
/// Prototype manager
///
class ColorManager
{
private Dictionary_colors =
new Dictionary();
// Indexer
public ColorPrototype this[string key]
{
get { return _colors[key]; }
set { _colors.Add(key, value); }
}
}
}
Ismert felhasználás
- Eszköztáraknál
- Alapvető plug-in mechanizmusoknál
- EJB/COM Szervereknél
Kapcsolódó minták
A Prototype és az Abstract Factory bizonyos tekintetben konkurens minták. Azonban használhatóak együtt is. Az Abstract Factory tárolhat egy olyan prototípus halmazt, amelyet klónozni akarunk, és a termék objektumokat adjuk vissza.
Felhasznált anyagok
0 megjegyzés :
Megjegyzés küldése