我正在编写的代码(MyService
)包括每个客户在处理过程中的特定点插入自己的计算器的能力。这是为了允许自定义业务规则。在计算完成时,我们知道各种各样的事情,其中一些可能与计算有关。将为特定的输入参数集创建MyService
并运行一次。
我的计划是使用依赖注入在构造函数中为MyService
calculator
提供一个calculator
。这允许不同的用户插入他们自己的calculator
。 MyService
将返回代表此特定MyService
运行应付附加费的金额。其他人将实现各种计算器,我需要能够更新我的代码而不会破坏他们的代码。即。保持向后兼容性。
我遇到的问题是各种计算器实现需要不同的参数。这些参数在创建MyService
时无法将构造函数注入计算器,因为不知道MyService
中的某些处理发生。
计算器只会在AlwaysZeroCalculator
的特定实例中调用一次。因此,在一个极端,所有参数都可以在构造函数中传递,并且有一个方法没有返回答案的参数。另一方面,所有参数都在方法调用中传递。
return 0
可能只是PercentageCalculator
所以不需要参数。 amount
需要amount
才能应用百分比。一个更复杂的需要customerNumber
和calculator
。我们可以假设MyService
在运行时可能知道calculator
可能需要的任何内容(或者它本身可以注入到ICalculator
实现中,就像hibernate Session一样。)
我该如何实现?
以下是一些选项和问题:
ICalculatorWithAmount
,ICalculatorWithAmountAndCustomerNumber
,MyService
等)。 calculator
需要查看它实现的calculate(..)
接口,将其强制转换为该接口,然后调用相应的calculator
方法。MyService
也取决于所有内容。calculatorFactory
的不同版本,以期望其中一个接口。calculator
而不是{{1}}。工厂将采用所有可能的参数,并创建一个只有正确的计算器。这似乎只是将问题转移到其他地方而没有解决它。有更好的方法吗?
答案 0 :(得分:2)
这是两个问题:
第一个很容易 - 所有计算器都做同样的事情,可以有相同的界面。 后者是要解决的问题,因为它需要每个计算器实例的不同参数。
从您列出的是工厂最佳解决方案。它并没有将问题转移到其他地方,它解决了这个问题。每个工厂都知道它的计算器并知道它需要什么参数。所以工厂依靠计算器。使用工厂创建计算器只会创建计算器而不是参数或计算器本身,它可以是所有工厂实现的工厂界面的一部分。
为工厂提供参数可以通过使用您选择的任何方式进行物业注入来解决 - 春天绝对不错。
应用程序反过来只知道如何使用计算器,因此取决于通用计算器接口而不是任何特定的计算器实现。
答案 1 :(得分:1)
假设你正在使用春天...... 也许bean标记的factory-bean和factory-method属性可能很有用。
伪代码......
<bean id="calculator1"
factory-bean="calculatorFactory"
factory-method="getAlwaysZeroCalculator">
<!--AlwaysZeroCalculator args go here -->
</bean>
<bean id="calculator2"
factory-bean="calculatorFactory"
factory-method="getPercentageCalculator ">
<!--PercentageCalculator args go here -->
</bean>
答案 2 :(得分:1)
我总是很难以优雅的方式获得运行时依赖项以使用依赖注入。
但是,我会针对您的“制作不同界面”计划进行修改。
每个计算器都会定义它自己的界面,比如IAlwaysZeroCalculatorParameters
,IPercentageCalculatorParameters
等。
然后,您的MyService
类可以实现所有这些接口,然后将其自身传递给每个计算器。
实现这一目标的框架开销很少,这意味着每个计算器都能简洁地表达它所需要的内容。在类似情况下,它对我来说非常有效,尽管在您的特定情况下(您无法控制插件),这意味着每次有人实施新计算器时您必须释放MyService
(以便它可以实现新的界面)。如果需要,我可能会用一些Duck Typing来解决这个问题。
答案 3 :(得分:0)
此calculator使用abstract
FunctionAdapter
按名称评估功能。每个具体的子类实现一个eval()
方法,该方法接受可变数量的参数。