如果 类 具有相同接口但方法签名相似但不同怎么办?
What to do if classes with same interface having similar but different method signature?
如果 类 相同接口具有相似但不同的方法签名怎么办?
假设我有一个项目来计算不同的成本(最终得到总成本)。
在我的程序中,有几个计算器类,即ACostCalculator
、BCostCalculator
等。当调用 calculate()
方法来计算成本时,成本容器也会传递给那些成本计算器。在一个好的场景中,我可以为每个成本计算器制作一个 CostCalculator
界面。
但是,计算不同的成本需要不同的资源。在我当前的程序中,它是这样的:
//getResource() are costly method while several costs need this. So do it outside calculate() method.
ResourceA resourceA = getResourceA();
ResourceB resourceB = getResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator aCostCalculator = new ACostCalculator();
...
CostCalculator eCostCalculator = new ECostCalculator();
aCostCalculator.calculate(costContainer);
bCostCalculator.calculate(costContainer)
cCostCalculator.calculate(costContainer, resourceA);
dCostCalculator.calculate(costContainer, resourceA);
eCostCalculator.calculate(costContainer, resourceA, resourceB);
如果签名完全相同,我可以方便地循环一次。但是,既然相似又不同,我连一个好的界面都做不出来。
不知道有没有好的方法。我能想到的是将所有 calculate()
方法概括为
calculate(CostContainer costContainer, List<Object> resources);
有什么想法吗?感谢您的回答。
您可以使用 variadic arguments:
public interface CostCalculatorInterface {
public void calculate(CostContainer container, Object... resources);
}
(或用 ResourceA
和 ResourceB
的另一个超类替换 Object
)。
在实现接口的类中,resources
将是一个Object[]
,因此您可以将它们称为resources[0]
、resources[1]
等.
如果资源在计算器的生命周期内保持不变:将资源传递给计算器的构造函数。
ResourceA resourceA = getResourceA();
ResourceB resourceB = getResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator aCostCalculator = new ACostCalculator();
CostCalculator bCostCalculator = new BCostCalculator();
CostCalculator cCostCalculator = new CCostCalculator(resourceA);
CostCalculator dCostCalculator = new DCostCalculator(resourceA);
CostCalculator eCostCalculator = new ECostCalculator(resourceA, resourceB);
aCostCalculator.calculate(costContainer);
bCostCalculator.calculate(costContainer);
cCostCalculator.calculate(costContainer);
dCostCalculator.calculate(costContainer);
eCostCalculator.calculate(costContainer);
这是您实际使用泛型的东西:
Resource resourceA = new ResourceA();
Resource resourceB = new ResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator<Resource> costCalculatorA = new ACostCalculator();
costCalculatorA.calculate(costContainer,resourceA,resourceB);
CostCalculator<Resource> costCalculatorB = new BCostCalculator();
costCalculatorB.calculate(costContainer,resourceA);
interface Resource {
//Your code
}
class ResourceA implements Resource {
//Your code
}
class ResourceB implements Resource {
//Your code
}
class CostContainer {
//Your code
}
interface CostCalculator<T extends Resource> {
void calculate(CostContainer costContainer, T... resources);
}
class ACostCalculator implements CostCalculator<Resource>{
@Override
public void calculate(CostContainer costContainer, Resource... resources) {
System.out.println("Test");
}
}
class BCostCalculator implements CostCalculator<Resource>{
@Override
public void calculate(CostContainer costContainer, Resource... resources) {
System.out.println("Test2");
}
}
通用接口的不同签名问题听起来很像 Adapter design pattern (object adapter variant) 解决的问题:
根据您的情况,您只需使用 non-conforming 计算器的适配器。实际上只有两种类型的适配器,用于签名 (costContainer, resourceA)
的 Type1 和用于签名 (costContainer, resourceA, resourceB)
的 Type2。使用您的示例:
适配器的优点是它是一种已知的设计模式(由 GoF 于 1995 年发布),它允许具有不同签名的最终 calculate(...)
方法。如果上下文发生变化(例如资源变化),适配器可以动态更新。
缺点显然是额外的类、间接等。它比选择的答案更复杂,但更灵活,特别是如果你不能修改适配器的API。
如果 类 相同接口具有相似但不同的方法签名怎么办?
假设我有一个项目来计算不同的成本(最终得到总成本)。
在我的程序中,有几个计算器类,即ACostCalculator
、BCostCalculator
等。当调用 calculate()
方法来计算成本时,成本容器也会传递给那些成本计算器。在一个好的场景中,我可以为每个成本计算器制作一个 CostCalculator
界面。
但是,计算不同的成本需要不同的资源。在我当前的程序中,它是这样的:
//getResource() are costly method while several costs need this. So do it outside calculate() method.
ResourceA resourceA = getResourceA();
ResourceB resourceB = getResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator aCostCalculator = new ACostCalculator();
...
CostCalculator eCostCalculator = new ECostCalculator();
aCostCalculator.calculate(costContainer);
bCostCalculator.calculate(costContainer)
cCostCalculator.calculate(costContainer, resourceA);
dCostCalculator.calculate(costContainer, resourceA);
eCostCalculator.calculate(costContainer, resourceA, resourceB);
如果签名完全相同,我可以方便地循环一次。但是,既然相似又不同,我连一个好的界面都做不出来。
不知道有没有好的方法。我能想到的是将所有 calculate()
方法概括为
calculate(CostContainer costContainer, List<Object> resources);
有什么想法吗?感谢您的回答。
您可以使用 variadic arguments:
public interface CostCalculatorInterface {
public void calculate(CostContainer container, Object... resources);
}
(或用 ResourceA
和 ResourceB
的另一个超类替换 Object
)。
在实现接口的类中,resources
将是一个Object[]
,因此您可以将它们称为resources[0]
、resources[1]
等.
如果资源在计算器的生命周期内保持不变:将资源传递给计算器的构造函数。
ResourceA resourceA = getResourceA();
ResourceB resourceB = getResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator aCostCalculator = new ACostCalculator();
CostCalculator bCostCalculator = new BCostCalculator();
CostCalculator cCostCalculator = new CCostCalculator(resourceA);
CostCalculator dCostCalculator = new DCostCalculator(resourceA);
CostCalculator eCostCalculator = new ECostCalculator(resourceA, resourceB);
aCostCalculator.calculate(costContainer);
bCostCalculator.calculate(costContainer);
cCostCalculator.calculate(costContainer);
dCostCalculator.calculate(costContainer);
eCostCalculator.calculate(costContainer);
这是您实际使用泛型的东西:
Resource resourceA = new ResourceA();
Resource resourceB = new ResourceB();
CostContainer costContainer = new CostContainer();
CostCalculator<Resource> costCalculatorA = new ACostCalculator();
costCalculatorA.calculate(costContainer,resourceA,resourceB);
CostCalculator<Resource> costCalculatorB = new BCostCalculator();
costCalculatorB.calculate(costContainer,resourceA);
interface Resource {
//Your code
}
class ResourceA implements Resource {
//Your code
}
class ResourceB implements Resource {
//Your code
}
class CostContainer {
//Your code
}
interface CostCalculator<T extends Resource> {
void calculate(CostContainer costContainer, T... resources);
}
class ACostCalculator implements CostCalculator<Resource>{
@Override
public void calculate(CostContainer costContainer, Resource... resources) {
System.out.println("Test");
}
}
class BCostCalculator implements CostCalculator<Resource>{
@Override
public void calculate(CostContainer costContainer, Resource... resources) {
System.out.println("Test2");
}
}
通用接口的不同签名问题听起来很像 Adapter design pattern (object adapter variant) 解决的问题:
根据您的情况,您只需使用 non-conforming 计算器的适配器。实际上只有两种类型的适配器,用于签名 (costContainer, resourceA)
的 Type1 和用于签名 (costContainer, resourceA, resourceB)
的 Type2。使用您的示例:
适配器的优点是它是一种已知的设计模式(由 GoF 于 1995 年发布),它允许具有不同签名的最终 calculate(...)
方法。如果上下文发生变化(例如资源变化),适配器可以动态更新。
缺点显然是额外的类、间接等。它比选择的答案更复杂,但更灵活,特别是如果你不能修改适配器的API。