如何提供不同插件采用不同参数的插件模型 [英] How to provide a plug-in model where different plug-ins take different parameters

查看:126
本文介绍了如何提供不同插件采用不同参数的插件模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写的代码( MyService )包括每个客户在处理中的特定点插入自己的计算器的能力。这是为了允许自定义业务规则。在计算完成时,我们知道各种各样的事情,其中​​一些可能与计算有关。 MyService 将为特定的一组输入参数创建并运行一次。



我的计划是使用依赖注入在构造函数中给出 MyService a calculator 。这允许不同的用户插入自己的计算器计算器将返回一个数额,表示该特定运行 MyService 应付的附加费用。其他的将会实现各种计算器,我需要能够更新我的代码而不会破坏它们。即。保持向后兼容性。



我遇到的问题是各种计算器实现将需要不同的参数。在 MyService 创建时,这些参数不能被构造器注入到计算器中,因为它们在 MyService



计算器只会在 MyService 的特定实例中被调用一次。因此,在一个极端,所有参数都可以在构造函数中传递,并且有一个方法没有返回答案的参数。另一方面,所有参数都在方法调用中传递。



AlwaysZeroCalculator 可能只是返回0 ,因此不需要任何参数。 百分比计算器需要金额以应用百分比。一个更复杂的需要金额 customerNumber 。我们可以假设,无论计算器可能需要什么,在运行时(或本身可以注入 MyService code>计算器实现,像一个hibernate Session)。



我该如何实现?



这里有一些选项和问题:




  • 使所有计算器实现一个包含所有参数的接口作为方法参数。但是,如果添加了一些额外的东西,那么他们都需要更改,这将不可避免地将其变成第二个选项。

  • 制作不同的界面( ICalculator ICalculatorWithAmount ICalculatorWithAmountAndCustomerNumber 等)。 MyService 将需要查看它实现的计算器的界面,将其转换到该接口,然后调用相应的计算(..)方法。

  • 引入包含任何他们关心的任何参数对象。这意味着即使最简单的计算器取决于所有内容。

  • 制作不同的界面和不同版本的 MyService 这些接口之一。

  • 注入 calculatorFactory 而不是 / code>。工厂将采取所有可能的参数,并创建一个只有正确的计算器。这个似乎只是将问题转移到其他地方,而不解决它。

  • 将一些可怕的哈希马函数传递给计算器并输入安全性,依赖关系的声明被阻止



有更好的方法吗?

解决方案

这两个问题:


  • 使用计算器

  • 实例化计算器



第一个很简单 - 所有的计算器都做同样的事情,可以有相同的界面。
后者是要解决的问题,因为它需要每个计算器实例的不同参数。



从您列出的是工厂最佳解决方案。而在其他地方也没有把问题解决,这是解决问题的。每个工厂都知道它的计算器,并知道它需要什么参数。所以工厂依赖于计算器。使用工厂创建计算器只会创建一个依赖于创建计算器而不是其参数或计算器本身,它可以是所有工厂实现的工厂接口的一部分。



为工厂提供参数可以通过使用您选择的任何方式通过物业注入来解决 - 春天绝对不错。



该应用程序反过来只知道如何使用一个计算器取决于一般的计算器接口,而不是任何特定的计算器实现。


The code I'm writing (MyService) includes the ability for each customer to plug-in their own calculator at a particular point in the processing. This is to allow customization of business rules. At the point the calculation is done we know a variety of things, some of which may be relevant to the calculation. MyService will be created for a particular set of input parameters and run once.

My plan is to use dependency injection to give MyService a calculator in the constructor. This allows different users to plug-in their own calculator. The calculator will return an amount representing the surcharge payable for this particular run of MyService. Others will be implementing a variety of calculators and I'll need to be able to update my code without breaking theirs. ie. keep backwards compatability.

The problem I have is that the various calculator implementations will require different parameters. These parameters can not be constructor injected into the calculator at the time MyService is created because they are not known some processing in MyService occurs.

The calculator will only be called once within a particular instantiation of MyService. Therefore at one extreme all parameters could be passed in the constructor and there is a method with no parameters that returns the answer. At the other, all parameters are passed in the method invocation.

AlwaysZeroCalculator might just return 0 so no parameters are required. PercentageCalculator needs amount in order to apply a percentage. A yet more complicated one needs the amount and customerNumber. We can assume that whatever the calculator might need is known to MyService at runtime (or itself can be injected into the calculator implementation, like a hibernate Session).

How can I implement this?

Here are some options and problems:

  • Make all calculators implement an interface that includes all parameters as method arguments. But, if something extra is added then they all need to change which will inevitably turn this into the second option.
  • Make different interfaces (ICalculator, ICalculatorWithAmount, ICalculatorWithAmountAndCustomerNumber, etc). MyService will need to see which interface the calculator it has implements, cast it to that interface, and then call the appropriate calculate(..) method.
  • Introduce a parameter object that includes anything any of them care about. This means even the simplest calculator depends on everything.
  • Make different interfaces and different versions of MyService that expect one of those interfaces.
  • Inject a calculatorFactory instead of a calculator. The factory would take all possible parameters and create a calculator with only the right ones. This seem to just move the problem to somewhere else without solving it.
  • Pass some horrible hashmap to the calculator and type safety, declaration of dependencies be damned

Is there a better way?

解决方案

These are two problems:

  • using a calculator
  • instantiating a calculator

The first one is easy - all calculators do the same thing, can have the same interface. The latter is the one to solve, since it requires the different parameter for each calculator instance.

From what you listed is the factory the best solution. And it is not moving the problem elsewhere, it is solving the problem. Each factory knows its calculator and knows what parameters it needs. So the factory depends on calculator. Creating a calculator using a factory only creates a dependency on creating a calculator and not its parameters or the calculator itself, it can be part of the factory interface that all the factories implement.

Providing parameters for the factory can be solved by property injection using whatever means you choose - Spring definitely not bad in that.

The application in turn only know how to use a calculator so depends on the general calculator interface and not any particular calculator implementation.

这篇关于如何提供不同插件采用不同参数的插件模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆