Wzorce projektowe, cz. 3 Prototype

Trzecia część z serii wpisów o wzorcach projektowych. Tym razem omówię wzorzec projektowy Prototyp (Prototype).

Prototyp jest wzorcem, opisującym mechanizm tworzenia nowych obiektów poprzez klonowanie jednego obiektu macierzystego. Mechanizm klonowania wykorzystywany jest wówczas, gdy należy wykreować dużą liczbę obiektów tego samego typu lub istnieje potrzeba tworzenia zbioru obiektów o bardzo podobnych właściwościach.


Diagram klas wzorca Prototype

Implementując ten wzorzec deklaruje się klasę Prototype z abstrakcyjną operacją klonującą clone(). Operacja ta jest implementowana w klasach dziedziczonych po Prototype. Klient chcąc stworzyć nowy obiekt wywołuje metodę clone() pośrednio, za pomocą zdefiniowanej przez siebie operacji z parametrem określającym wymaganą docelową klasę realizującą abstrakcję Prototype.

Przykładowa implementacja

<?php
abstract class Prototype{
    protected $name;

    public function __construct($name) {
        $this->name=$name;
    }
    abstract function __clone();
    public function getName() {
        return $this->name;
    }
}

class ConcretePrototype extends Prototype{

    public function __construct($name) {
        parent::__construct($name);
    }
    public function __clone() {}
}

// testy
$prototype = new ConcretePrototype("nazwa");
echo  $prototype->getName(); // wyswietli "nazwa"
$prototype2 = clone $prototype;
echo  $prototype2->getName(); // wyswietli "nazwa"
?>

Przykład z życia wzięty

Przypuśćmy, że tworzymy księgarnię internetową. Istnieje potrzeba stworzenia wielu obiektów książek o podobnych właściwościach (wspólna kategoria, autor itp.). Zamiast ustawiać pola dla każdego obiektu oddzielnie możemy wykonać klony i zmieniać tylko elementy unikalne.

<?php
abstract class Book {
    protected $title;
    protected $topic;
    abstract function __clone();
    public function getTitle() {
        return $this->title;
    }
    public function setTitle($title) {
        $this->title = $title;
    }
    public function getTopic() {
        return $this->topic;
    }
}

class PHPBook extends Book {
    public function __construct() {
        $this->topic = 'PHP';
    }
    function __clone() {
    }
}

class JAVABook extends Book {
    public function __construct() {
        $this->topic = 'JAVA';
    }
    function __clone() {
    }
}

//testy
$phpbook1 = new PHPBook();
$phpbook1->setTitle("Ksiazka1");
$phpbook2 = clone $phpbook1;
$phpbook2->setTitle("Ksiazka2");

$javabook1 = new JAVABook();
$javabook1->setTitle("Ksiazka1");
$javabook2 = clone $javabook1;
$javabook2->setTitle("Ksiazka2");

echo "Kategoria: ".$phpbook1->getTopic()." Tytul: ".$phpbook1->getTitle()."<br />";
echo "Kategoria: ".$phpbook2->getTopic()." Tytul: ".$phpbook2->getTitle()."<br />";
echo "Kategoria: ".$javabook1->getTopic()." Tytul: ".$javabook1->getTitle()."<br />";
echo "Kategoria: ".$javabook2->getTopic()." Tytul: ".$javabook2->getTitle()."<br />";
?>

Zastosowanie

Wzorzec Prototype można stosować w sytuacjach, gdy tworzona jest duża liczba obiektów tego samego typu. Stosuje się go głównie w celach optymalizacji, gdyż klonowanie obiektu jest szybsze niż jego stworzenie.

PS: Może ktoś napisze miarodajne testy? ;)

Powiązane tematy

Print Friendly, PDF & Email