具有方法关系的装饰模式

时间:2017-10-13 14:52:53

标签: php symfony decorator

我在PHP中使用了设计模式Decorator,我遇到了结构问题。

这是一个简单的例子来说明我的问题:

interface MyInterface {
    function showUsers($array);
    function showUser($i);
}

class MyCLass implements MyInterface {

    function showUsers($array)
    {
        foreach($array as $toto) {
            $this->showUser($toto);
        }
    }

    function showUser($i)
    {
        echo $i;
    }
}

class MyCLassDecorator implements MyInterface {

    private $inner;

    public function __construct(MyInterface $inner)
    {
        $this->inner = $inner;
    }

    function showUsers($array)
    {
        $this->inner->showUsers($array);
    }

    function showUser($i)
    {
        echo "User: $i";
    }
}

class MyCLassDecorator2 implements MyInterface {

    private $inner;

    public function __construct(MyInterface $inner)
    {
        $this->inner = $inner;
    }

    function showUsers($array)
    {
        $this->inner->showUsers($array);
    }

    function showUser($i)
    {
        $this->inner->showUser($i);
        echo " is wonderful";
    }
}

$myClass = new MyCLassDecorator2(new MyCLassDecorator(new MyCLass()));

$myClass->showUsers(["Alfred", "Bob", "Claire"]);

使用此代码,方法showUser of MyClassDecorator&永远不会调用MyClassDecorator2。

我该怎么办? 是否禁止调用同一类的另一种方法? (拆分我的代码真的不方便) 还有另一种方法吗? 我应该通过方法创建一个接口吗?

非常感谢:)

编辑:

这是我最终使用的解决方案,虽然我对此并不满意......

我的代码不是在方法中而是在接口(服务)中分割

这是:

interface IShowUsers {
    function showUsers($array);
}
interface IShowUser {
    function showUser($user);
}

class Services {
    static $showUsers;
    static $showUser;
}

class MyShowUsers implements IShowUsers {

    function showUsers($array)
    {
        foreach($array as $toto) {
            Services::$showUser->showUser($toto);
        }
    }
}

class MyShowUser implements IShowUser {
    function showUser($user)
    {
        echo $user;
    }
}

class MyShowUserDecorator implements IShowUser {

    private $inner;

    public function __construct(IShowUser $inner)
    {
        $this->inner = $inner;
    }

    function showUser($user)
    {
        echo "User: ";
        $this->inner->showUser($user)
    }
}

class MyShowUserDecorator2 implements IShowUser {

    private $inner;

    public function __construct(MyInterface $inner)
    {
        $this->inner = $inner;
    }

    function showUser($user)
    {
        $this->inner->showUser($user);
        echo " is wonderful";
    }
}

$myClass = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser()));

Services::$showUsers = new MyShosUsers();
Services::$showUser = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser()));

Services::$showUsers->showUsers(["Alfred", "Bob", "Claire"]);

如果您有更好的解决方案,我会很高兴知道它:)

当然,我使用装饰器模式在许多项目中以不同的方式使用这些装饰器,例如这些例子:

//no decorators
Services::$showUser = new MyShowUser();

//only the first
Services::$showUser = new MyShowUserDecorator(new MyShowUser());

//only the second
Services::$showUser = new MyShowUserDecorator2(new MyShowUser());

所以延伸似乎不是一个好的解决方案。

再次感谢您提供正确的方法:)

1 个答案:

答案 0 :(得分:0)

在我看来,你需要重新思考一下。如果您能够清楚地了解您要完成的工作,那么我们可以提供更多见解。但要直接回答您的问题,您可以extend上课,然后override方法。

http://sandbox.onlinephpfunctions.com/code/61c33b0ce98631986134bf78efcd0391f9b9ab67

<?php
interface MyInterface {
    function showUsers($array);
    function showUser($i);
}

class MyCLass implements MyInterface {

    function showUsers($array = ["Alfred", "Bob", "Claire"])
    {
        foreach($array as $toto) {
            $this->showUser($toto);
        }
    }

    function showUser($i)
    {
        echo $i;
    }
}

// Extend the class in order to override the methods.
class MyCLassDecorator extends MyCLass {

    // Also, try removing this method to see what it does. 
    function showUsers($array = [1,2,3])
    {
        foreach($array as $toto) {
            $this->showUser($toto);
        }
    }

    function showUser($i)
    {
        echo "c'est la fete chez $i";
    }
}

$myClass = new MyCLassDecorator();

$myClass->showUsers();

修改

不确定我是否清楚,但问题是您希望继承行为而不使用继承MyCLass如何了解MyCLassDecorator::showUser

foreach($array as $toto) {
    // The issue is this line. You're mixing `decorator` and `inheritance`. 
    // You should re-think your design. This will not work.
    $this->showUser($toto);
}