我正在编写的代码 (MyService
) 允许每个客户在处理过程中的特定点插入他们自己的计算器。这是为了允许自定义业务规则。在计算完成时,我们知道了很多事情,其中一些可能与计算有关。 MyService
将为一组特定的输入参数创建并运行一次。
我的计划是使用依赖注入(inject)在构造函数中为 MyService
提供一个 calculator
。这允许不同的用户插入他们自己的计算器
。 计算器
将返回代表此次 MyService
的特定运行应付附加费的金额。其他人将实现各种计算器,我需要能够在不破坏他们代码的情况下更新我的代码。 IE。保持向后兼容性。
我遇到的问题是各种计算器实现需要不同的参数。这些参数不能在 MyService
创建时通过构造函数注入(inject)到计算器中,因为它们不知道 MyService
中发生的某些处理。
计算器只会在 MyService
的特定实例中被调用一次。因此,在一个极端情况下,所有参数都可以在构造函数中传递,并且有一个没有参数的方法返回答案。另一方面,所有参数都在方法调用中传递。
AlwaysZeroCalculator
可能只是返回 0
所以不需要参数。 PercentageCalculator
需要 amount
才能应用百分比。一个更复杂的需要 amount
和 customerNumber
。我们可以假设 calculator
可能需要的任何东西在运行时为 MyService
所知(或者它本身可以注入(inject)到 calculator
实现中,就像 hibernate 一样 session )。
我该如何实现?
这里有一些选项和问题:
- 让所有计算器实现一个接口(interface),将所有参数作为方法参数。但是,如果添加了一些额外的东西,那么他们都需要改变,这将不可避免地变成第二种选择。
- 创建不同的接口(interface)(
ICalculator
、ICalculatorWithAmount
、ICalculatorWithAmountAndCustomerNumber
等)。MyService
将需要查看它实现的calculator
接口(interface),将其转换为该接口(interface),然后调用适当的calculate(..)
方法。 - 引入一个参数对象,其中包含他们关心的任何内容。这意味着即使是最简单的
计算器
也依赖于一切。 - 制作不同的接口(interface)和不同版本的
MyService
以期望这些接口(interface)之一。 - 注入(inject)
calculatorFactory
而不是calculator
。工厂将采用所有可能的参数并创建一个只包含正确参数的计算器。这似乎只是将问题转移到别处而不解决它。 - 将一些可怕的 HashMap 传递给计算器和类型安全,该死的依赖声明
有没有更好的办法?
最佳答案
这是两个问题:
- 使用计算器
- 实例化一个计算器
第一个很简单 - 所有计算器都做同样的事情,可以有相同的界面。 后者是要解决的问题,因为它需要为每个计算器实例使用不同的参数。
从你列出的工厂是最好的解决方案。它并没有把问题转移到别处,而是在解决问题。每个工厂都知道自己的计算器,知道自己需要什么参数。所以工厂要靠计算器。使用工厂创建计算器只会创建对创建计算器的依赖,而不是它的参数或计算器本身,它可以是所有工厂实现的工厂接口(interface)的一部分。
为工厂提供参数可以使用您选择的任何方式通过属性注入(inject)来解决 - Spring 在这方面绝对不错。
应用程序反过来只知道如何使用计算器,因此依赖于通用计算器接口(interface)而不是任何特定的计算器实现。
关于java - 如何提供不同插件采用不同参数的插件模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5562051/