Инструменты пользователя

Инструменты сайта


php:shablony_proektirovanija:generative_patterns:prototype

Прототип (Prototype)

Прототип — это порождающий паттерн проектирования, который позволяет копировать объекты, не вдаваясь в подробности их реализации.

У вас есть объект, который нужно скопировать. Как это сделать? Нужно создать пустой объект такого же класса, а затем поочерёдно скопировать значения всех полей из старого объекта в новый.

Прекрасно! Но есть нюанс. Не каждый объект удастся скопировать таким образом, ведь часть его состояния может быть приватной, а значит — недоступной для остального кода программы.

Но есть и другая проблема. Копирующий код станет зависим от классов копируемых объектов. Ведь, чтобы перебрать все поля объекта, нужно привязаться к его классу. Из-за этого вы не сможете копировать объекты, зная только их интерфейсы, а не конкретные классы.

Паттерн Прототип поручает создание копий самим копируемым объектам. Он вводит общий интерфейс для всех объектов, поддерживающих клонирование. Это позволяет копировать объекты, не привязываясь к их конкретным классам. Обычно такой интерфейс имеет всего один метод clone.

Реализация этого метода в разных классах очень схожа. Метод создаёт новый объект текущего класса и копирует в него значения всех полей собственного объекта. Так получится скопировать даже приватные поля, так как большинство языков программирования разрешает доступ к приватным полям любого объекта текущего класса.

Объект, который копируют, называется прототипом (откуда и название паттерна). Когда объекты программы содержат сотни полей и тысячи возможных конфигураций, прототипы могут служить своеобразной альтернативой созданию подклассов.

В этом случае все возможные прототипы заготавливаются и настраиваются на этапе инициализации программы. Потом, когда программе нужен новый объект, она создаёт копию из приготовленного прототипа.

interface IPost
{
    public function __clone();
}
 
class Post implements IPost
{
 
    private $title, $text;
 
    private $user;
    private $comment = [];
    private $created_at;
 
    public function __construct(User $user, $title, $text) {
 
        $this->user = $user;
        $this->title=$title;
        $this->text = $text;
        $this->created_at = new \DateTime();
 
        $this->user->addPost($this);
    }
 
    public function addComment($comment) {
        $this->comment[] = $comment;
    }
 
    public function __clone() {
        $this->title =  $this->title . "New Post";
        $this->user->addPost($this);
        $this->comments = [];
        $this->created_at = new \DateTime();
    }
}
 
class User {
 
    private $firstname;
 
    private $posts = [];
 
    public function __construct($firstname) {
        $this->firstname = $firstname;
    }
 
    public function addPost($post) {
        $this->posts[] = $post;
    }
 
}
 
$user = new User('User');
$post = new Post($user,'First Post','Hello world');
 
$post->addComment('Hello');
 
$post2 = clone $post;
 
var_dump($post2);
var_dump($post);
php/shablony_proektirovanija/generative_patterns/prototype.txt · Последние изменения: 2023/08/07 23:25 — werwolf