Design pattern Prototype give us control of making clones of objects
Design pattern Prototype give us control of making clones of objects. In php syntax, we have a special keyword/command clone
for making an object's copy. But it does not allow you to clone correctly some parameters that are implementations of other classes.
I propose to consider an example that can be encountered when developing a blog or an online publication. On such resources, one of the main entities is the Page, which, of course, has an author.
Let's implement this. The author will have, of course, a name, as well as the list of pages of this author. In this case, the list will contain not just an id, but a full-fledged page object.
class Author
{
public function __construct(
public readonly string $name,
private array $pages = []
) {}
public function addPage(Page $page): void
{
$this->pages[] = $page;
}
public function getPages(): array
{
return $this->pages;
}
}
Also, each page must have an author property that implements the Author class, in addition to other necessary data.
class Page
{
public function __construct(
private string $title,
private string $body,
public readonly Author $author,
private array $comments = [],
private \DateTime $date = new \DateTime()
) {
$this->author->addPage($this);
}
public function getTitle(): string
{
return $this->title;
}
public function setTitle(string $title): void
{
$this->title = $title;
}
public function getBody(): string
{
return $this->body;
}
public function setBody(string $body): void
{
$this->body = $body;
}
public function getComments(): array
{
return $this->comments;
}
public function addComment(string $comment): void
{
$this->comments[] = $comment;
}
public function getDate(): \DateTime
{
return $this->date;
}
}
Now, with such a structure, cloning pages becomes not an easy task for PHP. And this may well be necessary if the author wants to make a copy of his article, which in the future will publish a new one based on it. It is for this situation that the Prototype template exists, which allows you to configure exactly how to clone complex objects.
Let's add an implementation of the magic cloning method to the Page class, in which we will describe exactly how we need to clone objects of this class.
public function __clone()
{
$this->title = "Copy of " . $this->title;
$this->author->addPage($this);
$this->comments = [];
$this->date = new \DateTime();
}
Of course, we can implement more complex logic in the method. In practice, the Page can refer to more other objects in its properties. In such a case, the Prototype can be a very useful approach.