今天工作中遇到这样一种情况,有一个父类,下面有非常多各种各样的子类,同时有这样一个总类,它包含了前面说的子类的所有属性,同时还拥有一个属性type标志它对应前面说的子类内容。这个总类实例要和前面的一堆子类实例进行比较,那堆子类是挂在List<父类>下的,比较时总类要根据type找到对应的子类对象,才可以比较。文字不好说明,看下面的代码(类似工作中遇到的情形)。
package com.fei;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WifeFindHusband {
public static void main(String[] args) {
//TallHusband/FatHusband的父类是Husband
List<Husband> husbands = new ArrayList<Husband>();
//public TallHusband(String name, String secondName)
husbands.add(new TallHusband("李明","狗娃"));
//public FatHusband(String name, int age)
husbands.add(new FatHusband("张华",18));
//public Wife(String name, String husbandType, String husbandName,String husbandSecondName, int husbandAge)
List<Wife> wifes = new ArrayList<Wife>();
wifes.add(new Wife("陈红","tall","李明","狗娃",0));
wifes.add(new Wife("林丽","fat","张华","",25));
//妻子找丈夫,tall 对于 TallHusband,fat 对于 FatHusband
//先判断丈夫类型,在详细比较
find1(wifes,husbands);
find2(wifes,husbands);
// Husband h = new TallHusband("李明","狗娃");
// TallHusband th = TallHusband.class.cast(h);
}
/**缺点: 如果丈夫类型有非常多(Husband的子类特别多),则if else if的判断会非常多
*有新类型的丈夫加入时,该方法需要修改它,多加else if判断
*优点:类型转换有保证,掉用CompatorHelper时,编译期就能准确知道调用哪个方法
*/
private static void find1( List<Wife> wifes ,List<Husband> husbands){
for(Wife wife : wifes){
boolean isFind = false;
for(Husband husband : husbands){
if("tall".equals(wife.getHusbandType()) && husband instanceof TallHusband){
isFind =CompatorHelper. isCouple(wife,TallHusband.class.cast(husband));
}else if("fat".equals(wife.getHusbandType()) && husband instanceof FatHusband){
isFind = CompatorHelper.isCouple(wife,(FatHusband)husband);
}
if(isFind) break;
}
if(isFind){
System.out.println("妻子"+wife.getName()+"找到丈夫了");
}else{
System.out.println("妻子"+wife.getName()+"没到丈夫了");
}
}
}
private static Map<String,Class<? extends Husband>> HUSBAND_TYPE;
static{
HUSBAND_TYPE = new HashMap<String,Class<? extends Husband>>();
HUSBAND_TYPE.put("tall", TallHusband.class);
HUSBAND_TYPE.put("fat", FatHusband.class);
}
/**
* 优点:当有新丈夫类型加入时,只需HUSBAND_TYPE中增加配置即可,不需要修改find2方
* 缺点:调用CompatorHelper中的方法时,无法在编译期就能检查到是否存在
*/
private static void find2( List<Wife> wifes ,List<Husband> husbands){
for(Wife wife : wifes){
boolean isFind = false;
Class<? extends Husband> husbandType = HUSBAND_TYPE.get(wife.getHusbandType());
if(husbandType != null){
for(Husband husband : husbands){
if(husbandType == husband.getClass()){
//无法用这中形式,因为编译期无法确定husbandType.cast(husband)的具体类型,编译器报错
//所以考虑用反射,突破编译器的约束
// isFind = CompatorHelper.isCouple(wife, husbandType.cast(husband));
try {
Method m= CompatorHelper.class.getMethod("isCouple",wife.getClass(), husbandType);
isFind =(boolean) m.invoke(null,wife,husband);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("妻子找丈夫报错,CompatorHelper类isCouple方法无"+husbandType.getName()+"这种类型的丈夫");
}
}
if(isFind) break;
}
}
if(isFind){
System.out.println("妻子"+wife.getName()+"找到丈夫了");
}else{
System.out.println("妻子"+wife.getName()+"没到丈夫了");
}
}
}
}
package com.fei;
public class CompatorHelper {
public static boolean isCouple(Wife wife ,TallHusband husband){
if(wife.getHusbandName().equals(husband.getName())
&& wife.getHusbandSecondName().equals(husband.getSecondName())){
return true;
}
return false;
}
public static boolean isCouple(Wife wife ,FatHusband husband){
if(wife.getHusbandName().equals(husband.getName())
&& wife.getHusbandAge() == husband.getAge()){
return true;
}
return false;
}
}
想了想,还是倾向于用find1方法,虽然会有很多if else if的判断,但是对CompatorHelper的调用可以在编译期就可以保证必须有对应的方法。如果用find2方法,由于哟哦那个了反射,如果CompatorHelper缺少了某些方法,在编译期也不报错,在运行期才会报错,风险较大,除非测试充分,把所有的丈夫类型都测试一遍。
4867

被折叠的 条评论
为什么被折叠?



