PHP 中的仆人模式示例


Examples of servant pattern in PHP?

PHP中是否有任何仆人模式示例?似乎它不是很流行的模式,但我发现它非常有用,它比命令模式更简单。是反模式吗?

我可以找到它是用其他语言实现的,例如在这种语言中(我不知道它是什么语言,但看起来像java)。

我的例子:

// Servant.
interface Servant
{
    //  
}
// Servable.
interface Servable
{
    //
}
// Concrete Servable.
class ConcreteServable implements Servable
{
    private $position;
    public function setPosition($position)
    {
        $this->position = $position . '<br/>';
    }
    public function getPosition()
    {
        return $this->position;
    }
}
// Concrete Servant.
class ConcreteServant implements Servant
{
    // Method, which will move Servable implementing class to position where.
    public function moveTo(Servable $Servable, $arg) 
    {
        // Do some other stuff to ensure it moves smoothly and nicely, this is
        // the place to offer the functionality.
        $Servable->setPosition($arg);
    }
}
$ConcreteServable = new ConcreteServable();
$ConcreteServant = new ConcreteServant();
$ConcreteServant->moveTo($ConcreteServable, 10);
echo $ConcreteServable->getPosition(); // 10

但不确定我是否正确。 有什么想法吗?

Servant 模式不像 PHP 中的其他模式那样被注意到,但这是由于经常发生在服务中。这不是一个反模式

在您的示例中,接口没有指定类必须实现的任何方法,接口的原因是强制类具有您所追求的方法。

我以这里找到的仆人模式为例,并将其转换为PHP以供参考。

这确实展示了PHP的Servant模式的一个很好的例子,但我不会用它来做这么简单的事情。


class Position {
    /** @var int  */
    public $x = 0;
    /** @var int  */
    public $y = 0;
}
interface PositionedInterface {
    public function getPosition(): Position;
    
    public function setPosition(Position $position): void;
}
class MoveServant {
    public static function moveTo(PositionedInterface $positioned, int $xMoveTo, int $yMoveTo): void
    {
        /** @var Position $newPosition */
        $newPosition = new Position;
        $newPosition->x = $xMoveTo;
        $newPosition->y = $yMoveTo;
        $positioned->setPosition($newPosition);
    }
    public static function moveBy(PositionedInterface $positioned, int $xMoveBy, int $yMoveBy): void
    {
        /** @var Position $startPosition */
        $oldPosition = $positioned->getPosition();
        /** @var Position $newPosition */
        $newPosition = new Position;
        $newPosition->x = $oldPosition->x + $xMoveBy;
        $newPosition->y = $oldPosition->y + $yMoveBy;
        $positioned->setPosition($newPosition);
    }
}
class Triangle implements PositionedInterface
{
    /** @var Position */
    private $position;
    function __construct()
    {
        $this->position = new Position();
    }
    /**
     * @return Position
     */
    public function getPosition(): Position
    {
        return $this->position;
    }
    /**
     * @param Position $position
     */
    public function setPosition(Position $position): void
    {
        $this->position = $position;
    }
}
// Only fully typed out instead of extended to match example from link in question 
class Ellipse implements PositionedInterface
{
    /** @var Position */
    private $position;
    function __construct()
    {
        $this->position = new Position();
    }
    /**
     * @return Position
     */
    public function getPosition(): Position
    {
        return $this->position;
    }
    /**
     * @param Position $position
     */
    public function setPosition(Position $position): void
    {
        $this->position = $position;
    }
}
// Only fully typed out instead of extended to match example from link in question 
class Rectangle implements PositionedInterface
{
    /** @var Position */
    private $position;
    function __construct()
    {
        $this->position = new Position();
    }
    /**
     * @return Position
     */
    public function getPosition(): Position
    {
        return $this->position;
    }
    /**
     * @param Position $position
     */
    public function setPosition(Position $position): void
    {
        $this->position = $position;
    }
}

这将允许在实现PositionedInterface的任何类上使用MoveServant


$myTriangle = new Triangle();
// $myRectangle->getPosition()->x = 0
// $myRectangle->getPosition()->y = 0
MoveServant::moveBy($myTriangle, 15, 30);
// $myTriangle->getPosition()->x = 15
// $myTriangle->getPosition()->y = 30
$myEllipse = new Ellipse();
// $myRectangle->getPosition()->x = 0
// $myRectangle->getPosition()->y = 0
MoveServant::moveBy($myEllipse, 20, 100);
// $myEllipse->getPosition()->x = 20
// $myEllipse->getPosition()->y = 100
MoveServant::moveBy($myEllipse, -18, -85);
// $myEllipse->getPosition()->x = 2
// $myEllipse->getPosition()->y = 15
$myRectangle = new Rectangle();
// $myRectangle->getPosition()->x = 0
// $myRectangle->getPosition()->y = 0
MoveServant::moveTo($myRectangle, 10, 20);
// $myRectangle->getPosition()->x = 10
// $myRectangle->getPosition()->y = 20
MoveServant::moveBy($myRectangle, 20, 10);
// $myRectangle->getPosition()->x = 30
// $myRectangle->getPosition()->y = 30