我有一个设计困境,其中:
我的网页上有一个UI操作,允许用户从类型列表中选择一种类型。
每种类型都由POJO定义。我需要在父类中包装此POJO(对于用户已选择的类型)并使用它来执行操作。
每种类型都可能导致不同的行为。
如何设计父类以支持用户选择的任何类型?我希望在我的应用程序中稍后使用选定的POJO时避免instanceof
检查。
答案 0 :(得分:3)
哪种解决方案最好取决于您在UI中定义选项的方式。
定义可能选择的最简单方法是使用枚举。如果你走这条路线,我建议使用EnumMap
将类型映射到动作,或者(假设动作是可变的或需要根据请求创建动作工厂。
例如:
EnumMap<Type, Class<Action>> typeToActionMap = new EnumMap<>();
typeToActionMap.put(Type.Large, LargeAction.class);
typeToActionMap.put(Type.Medium, MediumAction.class);
typeToActionMap.put(Type.Small, SmallAction.class);
上面我使用动作类作为一种工厂。如果动作可以是单例,则可以使地图的值成为动作。正如@dhke建议的那样,你可以使用Guava的ClassToInstanceMap
来映射:
ClassToInstanceMap<Action> actionTypeToAction = MutableClassToInstanceMap.create();
typeToActionMap.putInstance(LargeAction.class, new LargeAction(...));
typeToActionMap.putInstance(MediumAction.class, new MediumAction(...));
如果您已经为每个选择设置了唯一类型,那么您只需要找到一种方法来进行映射。一种简单的方法是让您的类型都实现一个通用的接口:
public interface ActionProvider {
Class<? extends Action> getActionClass();
答案 1 :(得分:1)
实施APP_ABI := all
。
ActionRegistry
然后,当您在用户界面中选择class ActionRegistry {
private static Map<ActionType, AbstractAction> REGISTRY = ...
public static void registerAction(AbstractAction a) {
REGISTRY.put(a.getType(), a);
}
public static AbstractAction getAction(ActionType type) {
REGISTRY.get(type);
}
}
时,您可以执行以下操作:
type
您可以试用ActionRegistry.getAction(type).run();
,因此在实例化其子类时,它会自动在注册表中注册。
答案 2 :(得分:0)
为了避免instanceof
,您可以覆盖一个方法,然后执行您需要的UI操作。
public void doAction(Type1 type) { //... }
public void doAction(Type2 type) { //... }
这种方法可以采取多种形式
interface Action {
void perform();
}
public class ActionFactory {
public static Action getAction(Type1 type) { //... }
public static Action getAction(Type2 type) { //... }
}