2017-10-13 60 views
0

我在PHP中使用设计模式装饰器,我有一个结构问题。装饰模式与方法关系

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

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"]); 

有了这个代码,MyClassDecorator & MyClassDecorator2的方法showUser将永远不会被调用。

我该怎么办? 禁止调用同一类的另一种方法吗? (不是很方便的分割我的代码) 有没有另一种方法来做到这一点? 我应该通过方法创建一个接口吗?

感谢很多:)

编辑:

这里是我最后使用的解决方案,虽然我不是很满意的吧...

我不是在拆我的代码方法,但在接口(服务)

这就是:

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"]); 

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

当然,我在这些exemples使用Decorator模式在许多项目中使用不同的方式处理这些装饰,如:

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

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

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

所以扩展似乎不是一个好的解决方案。

非常感谢你又给这样做的正确的方式:)

回答

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); 
} 
+0

是的,在这个小例子中它将是一个很好的解决方法,但是我在symfony服务中遇到了这个问题,它具有更复杂的功能和更多的装饰封装。所以我需要保持装饰模式,以避免擦除重写。 –

+0

您没有正确使用装饰模式,并且编辑了代码,所以我的示例现在已过时。你调用了'$ this-> inner-> showUsers($ array);'在MyCLass的一个实例上调用'showUsers',这就是为什么它没有使用MyCLassDecorator :: showUser。你必须'扩展'这个类,以便它知道重写方法,或者你需要正确使用装饰器模式。我会看看我能否拿出一个例子。 – waterloomatt

+0

我已经编辑了我的帖子,你现在可能会更好地理解我需要的东西:) 而且我确切的说,我不知道装饰者将使用哪种顺序。 –