Prototyp (návrhový vzor)

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. 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. 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). 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.[zdroj?]

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. 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ř. 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”. Pro metodu “clone” existují tři významná omezení:

  1. 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.
  2. Je možné klonovat pouze objekty, které implementují interface “Clonable”.
  3. Objekt, který není možné klonovat, vyhodí výjimku CloneNotSupported.

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

  1. obj.clone() != obj
  2. obj.clone().equals(obj)
  3. 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.clone();
        //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 < 10; i++) {
                tempExample = cm.makeCopy();
                tempExample.prototypeFactory(i * num);
                tempExample.printValue();
            }
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

PHP

<?php
class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->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)[zdroj?]. 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)[zdroj?]

Č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)[zdroj?].

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)[zdroj?].

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

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. 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”.[zdroj?]

Reference


Zdroj datcs.wikipedia.org
Originálcs.wikipedia.org/wiki/Prototyp_(návrhový_vzor)
Zobrazit sloupec 

Kalkulačka - Výpočet

Výpočet čisté mzdy

Důchodová kalkulačka

Přídavky na dítě

Příspěvek na bydlení

Rodičovský příspěvek

Životní minimum

Hypoteční kalkulačka

Povinné ručení

Banky a Bankomaty

Úrokové sazby, Hypotéky

Směnárny - Euro, Dolar

Práce - Volná místa

Úřad práce, Mzda, Platy

Dávky a příspěvky

Nemocenská, Porodné

Podpora v nezaměstnanosti

Důchody

Investice

Burza - ČEZ

Dluhopisy, Podílové fondy

Ekonomika - HDP, Mzdy

Kryptoměny - Bitcoin, Ethereum

Drahé kovy

Zlato, Investiční zlato, Stříbro

Ropa - PHM, Benzín, Nafta, Nafta v Evropě

Podnikání

Města a obce, PSČ

Katastr nemovitostí

Katastrální úřady

Ochranné známky

Občanský zákoník

Zákoník práce

Stavební zákon

Daně, formuláře

Další odkazy

Auto - Cena, Spolehlivost

Registr vozidel - Technický průkaz, eTechničák

Finanční katalog

Volby, Mapa webu

English version

Czech currency

Prague stock exchange


Ochrana dat, Cookies

 

Copyright © 2000 - 2024

Kurzy.cz, spol. s r.o., AliaWeb, spol. s r.o.