工厂方法重载咨询:基于超类子类实例构建差异化返回的工厂实现
基于子类实例匹配的工厂类实现方案
我手头有一组全部是SuperClass子类实例的列表,想要做一个工厂类,能根据传入的不同子类实例,返回对应的不同UI组件(比如EditText、CheckBox这类)。目前我写了一段示例代码,但遇到了个棘手的问题,想跟大家聊聊怎么解决或者优化:
public class SuperClass { ... } public class SubClass1 extends SuperClass { ... } public class SubClass2 extends SuperClass { ... } public class Factory { public static getInstance(SubClass1 item) { return new EditText(); } public static getInstance(SubClass2 item) { return new CheckBox(); } } public class Generator { public Generator() { List<SuperClass> items = ...; // 存放着一堆SuperClass子类的实例 for(SuperClass item : items) { // 这里卡壳了:item是SuperClass类型,没法直接调用Factory的重载方法 // 该怎么处理这种情况呢? } } }
目前写法的核心问题
现在的Factory用方法重载来区分不同子类,但当我们处理SuperClass类型的列表时,编译器没法自动识别item的实际子类类型,也就没法匹配到对应的重载方法,导致代码无法正常运行。
几种可行的解决方案
方案1:直接用instanceof判断(简单直接)
如果子类数量不多,这种写法最容易上手:
public class Factory { public static View getInstance(SuperClass item) { if (item instanceof SubClass1) { return new EditText(); } else if (item instanceof SubClass2) { return new CheckBox(); } // 兜底处理未知子类的情况 throw new IllegalArgumentException("不支持的子类类型:" + item.getClass()); } }
之后在Generator里就能直接调用了:
for(SuperClass item : items) { View view = Factory.getInstance(item); // 后续对view进行操作 }
方案2:利用多态(推荐,符合开闭原则)
把创建组件的逻辑下沉到子类里,这样以后新增子类的时候,完全不用修改现有代码:
首先把SuperClass改成抽象类,添加一个抽象方法:
public abstract class SuperClass { public abstract View createCorrespondingView(); }
然后让每个子类实现这个方法:
public class SubClass1 extends SuperClass { @Override public View createCorrespondingView() { return new EditText(); } } public class SubClass2 extends SuperClass { @Override public View createCorrespondingView() { return new CheckBox(); } }
这下Generator里的代码就变得超级简洁:
for(SuperClass item : items) { View view = item.createCorrespondingView(); // 后续处理 }
这种方式完全遵循开闭原则,以后加新的子类,只需要实现抽象方法就行,不用动任何老代码。
方案3:用Class映射表(灵活解耦)
如果不想修改SuperClass和子类的代码,可以用Map来存储类型和创建逻辑的映射:
import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; public class Factory { private static final Map<Class<? extends SuperClass>, Supplier<View>> VIEW_CREATORS = new HashMap<>(); // 静态初始化映射关系 static { VIEW_CREATORS.put(SubClass1.class, EditText::new); VIEW_CREATORS.put(SubClass2.class, CheckBox::new); } public static View getInstance(SuperClass item) { Supplier<View> creator = VIEW_CREATORS.get(item.getClass()); if (creator == null) { throw new IllegalArgumentException("不支持的子类类型:" + item.getClass()); } return creator.get(); } }
新增子类的时候,只需要在静态代码块里加一行映射就行,同样不用改动其他逻辑,还避免了一堆if-else判断。
内容的提问来源于stack exchange,提问作者Oleksandr Karpov
相关产品推荐
相关产品推荐

