Okay, so the goal here is to implement a strategy pattern that can be tested using any sort of automated testing tool.

I've been struggling with this problem conceptually for a few weeks now and I want to clarify it.

So the current setup is something like this:

<?php
// CreateReportUseCase.php
class CreateReportUseCase
{
 protected $factory;
 public function __construct(Factory $factory)
 {
    $this->factory = $factory;
  }

  public function create($params)
  {
    // based on something in the params
    // ask the factory to give us one of the strategy classes

    // for this example, let's assume I'm going to execute
    // a different strategy based on the user role.
    // e.g. Admin
    $strategy = $this->factory->make($params['user_role']);

    // execute the strategy using the data out of the params
    $strategy->execute($params);
  }
}

// Factory.php
class Factory
{
  protected $admin_strategy;
  protected $user_strategy;
  public function __construct(AdminStrategy $admin_strategy, UserStrategy $user_strategy)
  {
    $this->admin_strategy = $admin_strategy;
    $this->user_strategy = $user_strategy;
  }

  public function make($role)
  {
    switch($role)
    {
       case 'Admin':
         return $this->admin_strategy;
         break;
       case 'User':
         return $this->user_strategy;
         break;
    }
  }
}

AdminStrategy implements RoleStrategy
{
  public function execute($params)
  {
    // it's not important what we do here.
    return json_encode($params);
  }
}

Does this look sane to you? How could I improve it? To me, the factory looks like it's a bit awkward since it's just returning some injected dependency instead of instantiating a strategy.

有帮助吗?

解决方案

In the end, collecting all advice in the comments section, I went with making the Factory an actual Factory, providing it with a dictionary between some parameters like 'User' and a fully qualified namespace + class name.

This way the Factory isn't coupled with the actual strategies, and it actually builds instances instead of just passing an attribute back.

As suggested, the chosen strategy is then placed inside a property on the Context class.

其他提示

This switch case could be changed by polymorphism (as described in Martin Fowler book) .

In order to attend polymorphism, you can use abstract factory, which in each concrete factory inheriting from it, will contain the respective logic.

The class itself doesn't need to know which factory will comes from the constructor, it can be "Admin" , "User" or any other, since it inherits from IFactory.

许可以下: CC-BY-SA归因
scroll top