首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PHP中的Decorator模式动态实例化类

使用PHP中的Decorator模式动态实例化类
EN

Stack Overflow用户
提问于 2017-07-27 21:32:42
回答 1查看 243关注 0票数 1

通常,在使用装饰器模式时,我通常直接实例化类,其中一个在另一个中:

代码语言:javascript
复制
abstract class Handler
{
    public function __construct(Handler $handler = null)
    {
        $this->handler = $handler;
    }

    abstract public function handle();
}

class FirstHandler extends Handler
{
    public function handle()
    {
        // Just calls the next guy in the chain. Obviously, this isn't doing anything, it's just for example sake.
        $this->handler->handle();
    }
}

// ... and so on with the SecondHandler, ThirdHandler, FourthHandler

$chain = new FirstHandler(
    new SecondHandler(
        new ThirdHandler(
            new FourthHandler()
        )
    )
);

$chain->handle();

但是,随着链的可能性越来越大,比如20个处理程序,您可以看到代码会开始缩进太多,并且很难阅读,特别是如果链中的不同处理程序没有"FirstHandler“、"SecondHandler”这样简单的名称,但总的来说,它看起来并不好。

我想知道是否有一种方法可以动态实例化类,方法是将它们放在数组中,然后迭代数组,并将数组中的n+1元素作为构造函数参数传递给数组中的第n个元素。

我脑子里有这样的想法:

代码语言:javascript
复制
$chain = null;

$links = [
    FirstHandler::class,
    SecondHandler::class,
    ThirdHandler::class,
    FourthHandler::class
];

foreach ($links as $index => $link) {
    $chain = new $link(new $links[$index + 1]());
}

您可能会知道,第一个问题是$chain在每个调用中都会被覆盖。第二个问题是,即使使用循环,我仍然必须手动将每个处理程序传递到链中,而真正要做的就是以原来的方式创建四次,这实际上更糟。第三个问题是,我最终会得到一个超出界限的例外。

是否有一种方法可以像我的意图(可能是某种递归调用)所显示的那样动态实例化这个链,还是我注定要像以前那样执行它?

EN

回答 1

Stack Overflow用户

发布于 2017-07-27 21:53:24

下面是一个在构造函数中使用数组并使用array_shift从列表中删除第一项的示例。Handler::makeChain( $classes )让球滚起来.

代码语言:javascript
复制
class Handler
{
  private $handler;
  public function __construct( $chain )
  {
    if( empty( $chain ) === false )
    {
      $this->handler = static::makeChain( $chain );
    }
  }
  public static function makeChain( $chain )
  {
    $class = array_shift( $chain );
    return new $class( $chain );
  }
}

class FirstHandler extends Handler{}
class SecondHandler extends Handler{}
class ThirdHandler extends Handler{}
class FourthHandler extends Handler{}

$classes = array(
  'FirstHandler',
  'SecondHandler',
  'ThirdHandler',
  'FourthHandler',
);

$handler = Handler::makeChain( $classes );

var_dump( $handler );

// object(FirstHandler)#77 (1) {
// ["handler":"Handler":private]=>
//   object(SecondHandler)#78 (1) {
//   ["handler":"Handler":private]=>
//     object(ThirdHandler)#79 (1) {
//     ["handler":"Handler":private]=>
//       object(FourthHandler)#80 (1) {
//       ["handler":"Handler":private]=>
//         NULL
//       }
//     }
//   }
// }

带有__construct类型提示的第二个版本

代码语言:javascript
复制
class Handler
{
  private $handler;
  public function __construct( Handler $injectedHandler = null )
  {
    if( $injectedHandler )
    {
      $this->handler = $injectedHandler;
    }
  }
  public static function handlerFactory( $chain )
  {
    $instance = null;
    foreach( array_reverse( $chain ) as $class )
    {
      $instance = new $class( $instance );
    }
    return $instance;
  }
}

class FirstHandler extends Handler{}
class SecondHandler extends Handler{}
class ThirdHandler extends Handler{}
class FourthHandler extends Handler{}

$classes = array(
  'FirstHandler',
  'SecondHandler',
  'ThirdHandler',
  'FourthHandler',
);

$handler = Handler::handlerFactory( $classes );

var_dump( $handler );
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45361384

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档