[英]Java: How To Treat 2 Different Objects The Same, With The Same Code?
I have a situation where I have two different objects that do mostly the same thing, but that have a different API. 我遇到的情况是,我有两个不同的对象,它们执行的功能大致相同,但是具有不同的API。
If I could treat them the same I could use one method to take care of both of them. 如果我能一视同仁,我可以使用一种方法来照顾他们两个。
Basically, I need to iterate through either using a for loop. 基本上,我需要使用for循环进行迭代。 The two objects have different function names for getting the size and retriving the latest result inside of each: 这两个对象具有不同的函数名称,用于获取大小并检索每个对象内部的最新结果:
CustomUnMutableObj1.getMySize() CustomUnMutableObj2.getTotal() CustomUnMutableObj1.getMySize()CustomUnMutableObj2.getTotal()
CustomUnMutableObj1.getlastresult() CustomUnMutableObj2.getlastvalue() CustomUnMutableObj1.getlastresult()CustomUnMutableObj2.getlastvalue()
Is there anyway I can use the same for loop for both, without a big clumsy set of conditionals, and having the code being blind to the type of object? 无论如何,在没有大量笨拙的条件集且代码对对象类型视而不见的情况下,我可以为两者都使用相同的for循环吗?
If you can't modify the two classes in question so they implement a common interface, you could still get the same effect by writing some "adapter classes" : 如果您不能修改有问题的两个类,以便它们实现一个公共接口,则可以通过编写一些“适配器类”来达到相同的效果:
interface CustomObjInterface {
int getSize();
int getLatestResult();
}
class CustomUnMutableObj1Adapter implements CustomObjInterface {
private CustomUnMutableObj1 wrapped;
public CustomUnMutableObj1Adapter(CustomUnMutableObj1 wrapped) {
this.wrapped = wrapped;
}
@Override int getSize() {return wrapped.getMySize();}
@Override int getLatestResult() {return wrapped.getTotal();}
}
// and a similar class for CustomUnMutableObj2
and then use the adapters instead of the original objects: 然后使用适配器而不是原始对象:
void doStuff(CustomObjInterface obj) {
// do stuff with obj here, using getSize and getLatestResult
}
// call it like this, for a CustomUnMutableObj1
// If you had a CustomUnMutableObj2, you'd use a CustomUnMutableObj2Adapter instead
doStuff(new CustomUnMutableObj1Adapter(obj));
Something that is unclear: you said "iterate thru either using a for loop", does it mean that your method is getting either a Collection<Obj1>
or a Collection<Obj2>
, but not a Collection<Object>
which will contains both Obj1
and Obj2
? 尚不清楚的一件事:您说过“使用for循环迭代”,是否表示您的方法获取的是Collection<Obj1>
或Collection<Obj2>
,但不是同时包含两个Obj1
的Collection<Object>
和Obj2
吗? (My answer is base on the above assumption) (我的回答是基于上述假设)
IMHO, using adapter (as suggested in other answer) may not be a good choice for above case, because if you are passing in a List<Obj1>
, you have to construct a List<CustomUnMutableObj1Adapter>
and pass to your "common processing method" for which you still need a bunch of code to handle it, and you will create one adapter list + one adapter for each element for each invocation of process logic, which may not be a good idea 恕我直言,使用适配器(如其他答案所示)可能不是上述情况的好选择,因为如果要传递List<Obj1>
,则必须构造一个List<CustomUnMutableObj1Adapter>
并传递给您的“通用处理方法” ”,您仍然需要一堆代码来处理它,并且对于流程逻辑的每次调用,您将为每个元素创建一个适配器列表+一个适配器,这可能不是一个好主意
Of course the best way to solve is to introduce a common interface/superclass to give these operations a meaningful concept. 当然,最好的解决方法是引入公共接口/超类,以使这些操作有意义。 However if it is not a choice, you may see if the following helps you. 但是,如果这不是一个选择,则可能会看到以下内容对您有帮助。
One way to reduce the boiler-plate code is by using something similar to a template method (If you are familiar with Spring, there are a lot of similar template like this) 减少样板代码的一种方法是使用类似于模板方法的方法(如果您熟悉Spring,则有很多类似的模板)
eg (pseudo-code, not compiled) 例如(伪代码,未编译)
interface ProcessInfoExtractor<T> {
int getSize(T entity);
String getLastValue(T entity);
}
The above interface will be responsible to perform the "common" operation against a provided object. 上面的接口将负责对提供的对象执行“公共”操作。
Then make your processing method like this: 然后使您的处理方法如下:
void <T> process(Collection<? extends T> entities, ProcessInfoExtractor<T> infoExtractor) {
for (T entity : entites) {
System.out.println("size " + infoExtractor.getSize(entity)
+ " last value " + infoExtractor.getLastValue(entity));
}
}
so when you need to iterate thru a List<Obj1>
, simply do: 因此,当您需要遍历List<Obj1>
,只需执行以下操作:
process(obj1List,
new ProcessInfoExtractor<Obj1> (
@Override
int getSize(Obj1 obj1) { return obj1.getMySize(); }
@Override
String getLastValue(Obj1 obj1) { return obj1.getLastResult(); }
));
(Similar case for Obj2
) (与Obj2
类似的情况)
To ease caller, you can make 2 wrapper methods which internally call the above process
method, like 为了简化调用程序,您可以创建2个内部调用上述process
方法的包装方法,例如
void process(Collection<Obj1> obj1List) {
process(obj1List, obj1InfoExtractor); // assume extractor is stateless,
// you can create one and reuse it
};
void process(Collection<Obj2> obj2List) {
process(obj2List, obj2InfoExtractor); // assume extractor is stateless,
// you can create one and reuse it
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.