【问题标题】:Adding functionality to a class using dependency injection使用依赖注入向类添加功能
【发布时间】:2017-11-04 15:51:45
【问题描述】:

我正在寻找最适合我的问题的模式。我有一个定义我的服务类功能的接口

interface NegotiationInterface {
    abstract public function resetNegotiation(Negotiation $negotiantion);
} 

一个主类实现它

public class NegotiationService implements NegotiationInterface {

    public function __construct(…Some Dependencies…)
    {
    ….        
    }

    public function resetNegotiation(Negotiation $negotiantion){
    …. //All business logic
    }
}

NegotiationService 在 DI 容器(基于 Symfony)下注册,并通过其服务 ID 在整个应用程序中使用。

$negotiationService = $this->container->get(“negotiation_service”);
$negotiationService->resetNegotiation($negotiation);

但是我们的一些客户端(协商包含客户端信息),在调用resetNegotiation之后需要额外的步骤,例如我们常见的业务逻辑+调用webservice。我达到了装饰器模式,但我不确定这是否是使用 DI 时的最佳方法。如果是这样,我将如何与 DI 一起申请。我想根据客户动态加载这些额外的步骤。

【问题讨论】:

  • 此时,您的问题有两个很好的答案。如果答案对您有所帮助,请查看它们并接受一个。或者,对答案发表评论以进一步澄清。也就是说,我提供了一个复合模式的例子,我认为它在你的情况下应该很好用..

标签: php oop design-patterns


【解决方案1】:

我必须在工作中做很多这样的课程,我们通常使用适配器(如果我在设计模式上错了,请纠正我)。在您的情况下,您的适配器将如下所示:

public class NegotiationServiceAdapter implements NegotiationInterface {

    protected $negotiationService;

    public function __construct(NegotiationService $negotiationService)
    {
        $this->negotiationService = $negotiationService;
    }

    public function resetNegotiation(Negotiation $negotiation){
        $this->negotiationService->resetNegotiation($negotiation);

        //Rest of your custom code for that client
    }
}

请注意,我在构造函数中添加了每个人都使用的“通用”NegotiationService,然后在实现的函数中,您首先执行此实例的代码(或最后,取决于您的情况),然后是您的自定义代码。

【讨论】:

  • 假设我有一个客户客户端 A 和 B。因此客户端 A 需要调用 Web 服务方法,而 B 需要导出文件。我将如何实施它?我在考虑装饰器,但我不确定。 NegotiationA、NegotiationB 注入 Negotiation。
  • @dextervip 当您决定使用装饰器模式时,您已经很接近了。看看我的答案以获得更好的方法。
【解决方案2】:

我接触了装饰器模式,但我不确定这是否是使用 DI 时的最佳方法

Decorator 模式相比,Composite pattern 更适合此用例。我将对您的代码进行以下更改:

  1. NegotiationInterfaceNegotiationService 中的resetNegotiation 方法重命名为execute
  2. arraylist(可以容纳NegotiationInterface 实例)添加到NegotiationService 作为实例变量。
  3. NegotiationService中的构造函数请求一个额外的list/array参数并在构造函数中初始化它。

  4. NegotiationServiceexecute方法中,遍历列表并对其中的每个NegotiationInterface调用execute

完成上述更改后,您可以创建 NegotiationInterface 的不同实现,将它们添加到 array/list 并将其传递给 NegotiationService,这将简单地逐个遍历每个实例,然后在每个实例上调用 execute

例如:

$resetNegotiation = new ResetNegotiationNegotiationInterfaceImpl();
$callWebservice = new CallWebServiceNegotiationInterfaceImpl();
$negotiationInterfacesClient1 = array($resetNegotiation, $callWebservice);
$negotiationServiceClient1 = new NegotiationService($dependencies, $negotiationInterfacesClient1);
negotiationServiceClient1.execute($negotiation);

$exportFile = new ExportFileNegotiationInterfaceImpl();
$negotiationInterfacesClient2 = array($resetNegotiation, $exportFile);
$negotiationServiceClient2 = new NegotiationService($dependencies,$negotiationInterfacesClient2);
negotiationServiceClient2.execute($negotiation);

地点:

  • ResetNegotiationNegotiationInterfaceImpl 实现 NegotiationInterface 并包含重置服务的代码 execute 方法。这被clientclient2 重复使用。
  • CallWebServiceNegotiationInterfaceImpl 实现 NegotiationInterface 并包含调用 web 服务的代码 execute 方法。
  • ExportFileNegotiationInterfaceImpl 实现 NegotiationInterface 并包含导出文件的代码 execute 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    相关资源
    最近更新 更多