/ Gists / 7. Prototype
On gists

7. Prototype

PHP Patterns

pic.md Raw #

Prototype.php Raw #

<?php

interface Device {

    public function __construct (DevicesGroup $group);

    public function setUid (string $uid): void;

    public function save (): void;
}


class Computer implements Device {

    private $uid;
    private $group;

    public function __construct (DevicesGroup $group) {
        $this->group = $group;
    }

    public function setUid (string $uid): void {
        $this->uid = $uid;
    }

    public function save (): void {
        echo "Saving device with UID {$this->uid} to group {$this->group->getName()}" . PHP_EOL;
    }
}


class DevicesGroup {

    public $name;
    public $location;

    public function __construct (string $name, string $location) {
        $this->name = $name;
        $this->location = $location;
    }

    public function getName (): string {
        return $this->name;
    }

    public function getLocation (): string {
        $this->location;
    }
}


// USAGE
$greenGroup = new DevicesGroup("Green", "Warsaw");
$computer = new Computer($greenGroup);

$uids = [
    "aaa",
    "bbb",
    "ccc",
    "ddd",
    "eee",
    "fff",
    "ggg"
];

foreach ($uids as $uid) {
    $device = clone $computer;
    $device->setUid($uid);
    $device->save();
}

Prototype2.php Raw #

<?php

abstract class BookPrototype
{
    protected string $title;
    protected string $category;

    abstract public function __clone();

    public function getTitle(): string
    {
        return $this->title;
    }

    public function setTitle(string $title)
    {
        $this->title = $title;
    }
}


class BarBookPrototype extends BookPrototype
{
    protected string $category = 'Bar';

    public function __clone()
    {
    }
}


class FooBookPrototype extends BookPrototype
{
    protected string $category = 'Foo';

    public function __clone()
    {
    }
}


// USAGE
 $fooPrototype = new FooBookPrototype();
        $barPrototype = new BarBookPrototype();

        for ($i = 0; $i < 10; $i++) {
            $book = clone $fooPrototype;
            $book->setTitle('Foo Book No ' . $i);
           // $this->assertInstanceOf(FooBookPrototype::class, $book);
        }

        for ($i = 0; $i < 5; $i++) {
            $book = clone $barPrototype;
            $book->setTitle('Bar Book No ' . $i);
            //$this->assertInstanceOf(BarBookPrototype::class, $book);
        }

Prototype3.php Raw #

<?php

/**
 * Prototype.
 */
class Page
{
    private $title;

    private $body;

    /**
     * @var Author
     */
    private $author;

    private $comments = [];

    /**
     * @var \DateTime
     */
    private $date;

    // +100 private fields.

    public function __construct(string $title, string $body, Author $author)
    {
        $this->title = $title;
        $this->body = $body;
        $this->author = $author;
        $this->author->addToPage($this);
        $this->date = new \DateTime;
    }

    public function addComment(string $comment): void
    {
        $this->comments[] = $comment;
    }

    /**
     * You can control what data you want to carry over to the cloned object.
     *
     * For instance, when a page is cloned:
     * - It gets a new "Copy of ..." title.
     * - The author of the page remains the same. Therefore we leave the
     * reference to the existing object while adding the cloned page to the list
     * of the author's pages.
     * - We don't carry over the comments from the old page.
     * - We also attach a new date object to the page.
     */
    public function __clone()
    {
        $this->title = "Copy of " . $this->title;
        $this->author->addToPage($this);
        $this->comments = [];
        $this->date = new \DateTime;
    }
}

class Author
{
    private $name;

    /**
     * @var Page[]
     */
    private $pages = [];

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function addToPage(Page $page): void
    {
        $this->pages[] = $page;
    }
}


function clientCode()
{
    $author = new Author("John Smith");
    $page = new Page("Tip of the day", "Keep calm and carry on.", $author);

    // ...

    $page->addComment("Nice tip, thanks!");

    // ...

    $draft = clone $page;
    echo "Dump of the clone. Note that the author is now referencing two objects.\n\n";
    print_r($draft);
}


/*
JS Version

class Page {
    constructor(title, body, author) {
        this._title = title; // Podtržítko používáme k indikaci, že se jedná o "chráněnou" vlastnost
        this._body = body;
        this._author = author;
        this._comments = [];
        this._date = new Date();
    }

    addComment(comment) {
        this._comments.push(comment);
    }

    clone() {
        const cloned = new Page('COPY of ' + this._title, this._body, this._author);
        cloned._comments = [];
        cloned._date = new Date();
        return cloned;
    }
}

class Author {
    constructor(name) {
        this._name = name;
        this._pages = [];
    }

    addToPage(page) {
        this._pages.push(page);
    }
}

function clientCode() {
    const author = new Author("John Smith");
    const page = new Page("Tip of the day", "Keep calm and carry on.", author);

    page.addComment("Nice tip, thanks!");

    const draft = page.clone();
    console.log("draft", draft);
	console.log('page', page)
}

clientCode();


*/