vendredi 20 novembre 2015

Where should the invoker be placed for a Command design pattern when the command updates private properties of the receiver?

I gave myself an exercise to understand the Command design pattern. I created interfaces for Placeable, Placer, and Placement where the idea was Placer would use the Placement command to change Placeable. I used simple x,y values for the place values. X and y in Placeable are private. (Shouldn't they be? Otherwise anything could change the location.) As you can see in the code below, my 'invoker' ended up inside the 'receiver.' This doesn't look like the examples I found online. Like this http://ift.tt/1QSKxgg. But, those examples use public properties. Have I done something really wrong in my exercise? As an aside, aren't examples which use public properties bad in terms of encapsulation? What is the point of Command designs if anything could access public properties or methods?

<?php 

// receiver
interface Placeable
{
    public function locate();

    public function toPlace(Placement $placement);
}

// client
interface Placer
{
    public function place(Placeable $placeable, $x=0, $y=0);
}

// command
interface Placement
{
    public function setX($x=0);

    public function setY($y=0);

    public function getX();

    public function getY();
}

///////////////////////////////////////////////////////////////////////

// receiver
class Book implements Placeable
{
    private $x = 0;
    private $y = 0;

    public function locate()
    {
        return '(' . $this->x . ',' . $this->y . ')';
    }

    // invoker is inside the receiver, because the command changes private properties
    public function toPlace(Placement $placement)
    {
        $this->x = $placement->getX();
        $this->y = $placement->getY();
    }
}

// command
class PlacementCommand implements Placement
{
    private $x = 0;
    private $y = 0;

    public function setX($x=0)
    {
        $this->x = $x;
    }

    public function setY($y=0)
    {
        $this->y = $y;
    }

    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }
}

// client
class Person implements Placer
{
    public function place(Placeable $placeable, $x=0, $y=0)
    {
        $placement_command = new PlacementCommand();
        $placement_command->setX($x);
        $placement_command->setY($y);
        $placeable->toPlace($placement_command);
    }
}
?>
<pre>
<?php 
$book = new Book();
$person = new Person();
$person->place($book, 3, 4);
//
echo var_dump($book);
?>
</pre>

Aucun commentaire:

Enregistrer un commentaire