Prototyp (návrhový vzor)

Technology
12 hours ago
8
4
2
Avatar
Author
Albert Flores

Návrhový vzor Prototype patří do rodiny tzv. creational design patterns (vytvářecí návrhové vzory).

Používá se, když je vytváření instance třídy velmi časově náročné nebo nějak výrazně složité. Potom je výhodnější než náročně vytvářet mnoho instancí, vytvořit jednu a ostatní objekty z ní naklonovat. +more Může být také použit když jsou potřeba třídy, které se liší pouze v tom, jaké zpracování nabízejí.

Klonování se provádí implementací speciální metody, která vytvoří klon aktuálního objektu. Metoda může využívat systémové metody pro klonování (viz níže) nebo může objekt vytvářet jiným způsobem. +more Také může obsahovat další operace s objektem (změnu některých dat a vlastností objektu).

Obdobnou funkčnost může také poskytovat tovární metoda, která je jednodušší na implementaci.

Standardní výsledek klonování je tzv. mělká kopie (pokud je v objektu odkaz na další objekt, zkopíruje se pouze reference). +more Pro získání tzv. hluboké kopie (nekopírují se pouze reference, ale celé objekty) je možné buď takovou funkcionalitu integrovat od implementace metody clone objektu nebo se vytváří nová metoda deepClone.

Význam použití návrhového vzoru Prototype

Použitím návrhového vzoru Prototype je možné přidávat a odebírat třídy za běhu klonováním, kdykoliv je potřeba. Je možné korigovat vnitřní data v závislosti na stavu programu. +more Je také možné specifikovat nové objekty, bez množení struktur tříd a dědičnosti. Třídy, které mají zacyklené reference na další objekty nemohou být klonovány. Využívá se i tzv. registr Prototypů (podobně jako registr Singletonů), kdy klonování obstarává registr a program se dotazuje registru. Jak bylo zmíněno, při klonování může být vyžadováno měnit některá data v závislosti na požadavcích programu. Pokud je taková potřeba očekávána, měla by třída implementovat také metody na práci s daty objektu - číst a přiřazovat hodnoty do atributů objektu.

Klonování

Výhodou klonování je, že program může pracovat s daty a různě je upravovat bez obav, že to ovlivní další části programu. To se může hodit např. +more při vracení interního pole (či kontejneru).

Implementace

Java

Klonování v jazyku Java je řešeno pomocí metody “clone”. Metoda vždy vrací objekt typu “Object”. +more Pro metodu “clone” existují tři významná omezení: # Je to metoda s přístupem “protected”. To znamená, že může být zavolána pouze v rámci třídy nebo z modulu, který třídu obsahuje. # Je možné klonovat pouze objekty, které implementují interface “Clonable”. # Objekt, který není možné klonovat, vyhodí výjimku CloneNotSupported.

Výsledek klonování by měl splňovat následující podmínky:

# obj.clone != obj # obj.clone.equals(obj) # obj.clone.getClass == obj.getClass

Potíž v implementaci návrhového vzoru Prototype v jazyce Java je, že pokud už třída existuje, nemusí být možné implementovat metody clone nebo deepClone. Speciálně metodu deepClone může být obtížné implementovat, pokud není možné deklarovat všechny objekty v třídě tak, aby implementovaly interface Serializable.

/** * Prototype Class */ abstract class PrototypeFactory implements Cloneable { public PrototypeFactory clone throws CloneNotSupportedException { // call Object. clone PrototypeFactory copy = (PrototypeFactory) super. +moreclone; //In an actual implementation of this pattern you might now change references to //the expensive to produce parts from the copies that are held inside the prototype. return copy; }.

abstract void prototypeFactory(int x);

abstract void printValue; }

/** * Concrete Prototypes to clone */ class PrototypeImpl extends PrototypeFactory { int x;

public PrototypeImpl(int x) { this.x = x; }

void prototypeFactory(int x) { this.x = x; }

public void printValue { System.out.println("Value :" + x); } }

/** * Client Class */ public class PrototypeExample {

private PrototypeFactory example; // Could have been a private Cloneable example.

public PrototypeExample(PrototypeFactory example) { this.example = example; }

public PrototypeFactory makeCopy throws CloneNotSupportedException { return this.example.clone; }

public static void main(String args[]) { try { PrototypeFactory tempExample = null; int num = 1000; PrototypeFactory prot = new PrototypeImpl(1000); PrototypeExample cm = new PrototypeExample(prot); for (int i = 0; i

PHP

instance = ++self::$instances; }

public function __clone { $this->instance = ++self::$instances; } }

class MyCloneable { public $object1; public $object2;

function __clone { // Force a copy of this->object, otherwise // it will point to same object. $this->object1 = clone $this->object1; } }

$obj = new MyCloneable;

$obj->object1 = new SubObject; $obj->object2 = new SubObject;

$obj2 = clone $obj;

print("Original Object:\n"); print_r($obj);

print("Cloned Object:\n"); print_r($obj2);

?>

Python

import copy

# # Prototype Class # class Cookie: def __init__(self, name): self.name = name

def clone(self): return copy.deepcopy(self)

# # Concrete Prototypes to clone # class CoconutCookie(Cookie): def __init__(self): Cookie.__init__(self, 'Coconut')

# # Client Class # class CookieMachine: def __init__(self, cookie): self.cookie = cookie

def make_cookie(self): return self.cookie.clone

if __name__ == '__main__': prot = CoconutCookie cm = CookieMachine(prot)

for i in xrange(10): temp_cookie = cm.make_cookie

Empirická pravidla (rules of thumb)

Někdy se návrhové vzory překrývají - jsou případy, kdy Prototyp ani Abstraktní továrna nebude vhodné použít. Jindy zase doplňují jeden druhý: Abstraktní továrna může ukládat sadu Prototypů, ze kterých se klonuje a vracejí se objekty (GoF, p126). +more Abstraktní továrna, Stavitel a Prototyp mohou použít při implementaci Jedináčka (Singleton) (GoF, p81, 134). Abstraktní továrna je často implementována s Tovární metodou (vytváření přes dědičnost), ale mohou být také vytvořeny pomocí Prototypu (vytváření přes pověření). (GoF, p95).

Často začnou programátoři používat Tovární metodu (jednodušší, více přizpůsobitelná) a následně se vyvine v Abstraktní továrnu, Prototyp nebo Stavitele (pružnější, komplexnější) poté, co programátor zjistí, kde je potřeba více flexibility (GoF, p136).

Rozdíl mezi Prototypem a Tovární metodou je, že Prototyp nevyžaduje dědění tříd, vyžaduje ale úvodní inicializaci. Naopak Tovární metoda vyžaduje dědění tříd, nevyžaduje inicializaci (GoF, p116).

Z Prototypu může mít užitek i design, který hojně využívá vzory Strom a Dekorátor. (GoF, p126)

Pokud budete potřebovat zavolat metodu clone na objektu, když budete chtít vytvořit další objekt při běhu, který je skutečnou kopií objektu, který klonujete. Skutečná kopie znamená, že všechny atributy nově vytvořeného objektu by měly být stejné, jako u původního. +more Pokud by byla třída vytvořena pomocí klíčového slova “new”, měl by objekt všechny hodnoty s výchozími hodnotami. Např. pokud navrhujete systém pro bankovní operace, budete chtít vytvořit kopii objektu, který udržuje informace o vašem účtu, provést na něm požadované operace a potom jím přepsat původní objekt. V tomto případě budete chtít použít metodu clone místo “new”.

Reference

, slangově GoF z Gang of Four

Kategorie:Programovací jazyky Kategorie:Návrhové vzory

5 min read
Share this post:
Like it 8

Leave a Comment

Please, enter your name.
Please, provide a valid email address.
Please, enter your comment.
Enjoy this post? Join Cesko.wiki
Don’t forget to share it
Top