Symfony2服务的外观模式

时间:2015-03-29 21:28:55

标签: symfony service facade

Symfony2新手,我正在构建一个使用外部API获取数据的应用。我创建了很多客户端类来从API中检索和转换每个实体,我将这些类定义为服务 - 例如,我有一个FooClient,其中包含getAll()getThoseThatInterestMe($me)等方法,从API返回数据。

现在我想创建一个ApiClientFacade类,它在Facade Pattern之后作为所有XxxClient类前面的接口 - 例如,这个Facade类将有一个方法getAllFoo(),反过来会调用FooClient::getAll(),依此类推......

我可以将我的外观类定义为服务,但它有太多的依赖项 - 我有大约30个客户端类。另外,使用这种方法afaik我每次都会加载所有30个依赖项,而大多数时候我只需要一个依赖项...

那么,有没有更好的方法呢?

1 个答案:

答案 0 :(得分:3)

使用额外的ApiClientFactory来移动ApiClient对象"实例化的责任"来自你的ApiFacade课程(根据我的理解,这是你最初的想法)。

在一些伪PHP代码中,我的想法是:

$api = new ApiFacade(new ApiClientFactory);
$api->sendNotificationAboutUserLogin('username', time());

方法的一个例子:

class ApiFacade {
  private $apiFactory;

  public function __construct(ApiClientFactory $factory)
  {
      $this->apiFactory = $factory;
  }    
  public function sendNotificationAboutUserLogin($username, $timeOfOperation)
    {
      return $this->apiFactory
          ->createApi('User')
          ->post(
              'notifications',
              array('operation' => 'login', 'username' => $username, 'timeOfOperation' => $timeOfOperation)
          );
    }
}

在这种情况下,您的Facade类保持可注入(可测试),但也变得更容易实例化(您不再需要将所有依赖项传递给它)。

ApiClientFactory应该是这样的:

class ApiClientFactory {
    private $apiBaseUrl;
    public function __construct($apiBaseUrl)
    {
      $this->apiBaseUrl = $apiBaseUrl;
    }
    public function createApi($apiName)
    {
      switch ($apiName) {
        case 'User': return new \My\UserApi($this->apiBaseUrl);
        default: // throw an exception?
      }
    }
}