在 Java 中使用 Enum 进行工厂,最佳实践?
Posted
技术标签:
【中文标题】在 Java 中使用 Enum 进行工厂,最佳实践?【英文标题】:Using Enum for factory in Java, a best practice? 【发布时间】:2013-07-09 00:18:09 【问题描述】:Java 允许我们在 Enum 上嵌入数据和行为。 我不想直接在 Enum 上实现工厂,因为我认为这不是它的作用。
但我可以将类引用放在枚举上,并在外部工厂上构造对象。与传统的工厂模式相比,最适合您的实现方式是什么?在哪种情况下使用哪种解决方案更好?
现在,代码。
两种解决方案中用于构造对象的函数。如果需要,可用于使用 Map 实现 fly-weight 模式。
private Action getAction(Class<? extends Action> actionClazz)
// logger + error handling
return actionClazz.newInstance();
1) 与传统工厂:
public enum ActionEnum
LOAD_DATA,
LOAD_CONFIG;
public Action getAction(ActionEnum action)
switch (action)
case LOAD_CONFIG:
return getAction(ActionLoadConfig.class);
case LOAD_DATA:
return getAction(ActionLoadData.class);
2) 使用枚举式工厂:
public enum ActionEnum
LOAD_DATA(ActionLoadConfig.class),
LOAD_CONFIG(ActionLoadData.class);
public ActionEnum(Class<? extends Action> clazz)...
public Class<? extends Action> getClazz() return this.clazz
public Action getAction(ActionEnum action)
return getAction(action.getClazz());
【问题讨论】:
你能给我一个 main 函数中第二个的例子吗? (我想看看这家工厂的用法),这个问题是4年前的问题,还是最好的方法吗? 【参考方案1】:第二个更简洁:它不需要任何长的 switch 块,并且像第一个一样忘记其中一个枚举值的风险为 0。
但并不总是可以使用它,因为枚举可能是一些通用枚举(例如Month
),不应与动作工厂耦合。
【讨论】:
【参考方案2】:应尽可能避免 IMO 调用 newInstance()
,因为它公然破坏了 java 提供的一些编译时保护(阅读其 javadoc)并引入了新的 Exception
s 来处理。
这里有一个类似于what Sergey provided 的解决方案,只是由于功能接口和方法引用而更加简洁。
public enum ActionEnum
LOAD_DATA(ActionLoadData::new),
LOAD_CONFIG(ActionLoadConfig::new)
private Supplier<Action> instantiator;
public Action getInstance()
return instantiator.get();
ActionEnum(Supplier<Action> instantiator)
this.instantiator = instantiator;
public Action getAction(ActionEnum action)
return action.getInstance();
【讨论】:
这是一个非常优雅的解决方案。非常感谢!【参考方案3】:这对我有用:
enum ActionEnum
LOAD_DATA
@Override
public ActionLoadData getInstance()
return new ActionLoadData ();
,
LOAD_CONFIG
@Override
public ActionLoadConfig getInstance()
return new ActionLoadConfig();
;
public abstract ILightBulb getInstance();
class ActionFactory
public Action getAction(ActionEnum action)
return action.getInstance();
【讨论】:
这是一个非常优雅的解决方案。非常感谢!【参考方案4】:进一步解耦:
static final EnumMap<ActionEnum, Class<? extends Action>> enumToClass = new EnumMap<>();
static
enumToClass.put(ActionEnum.LOAD_DATA, ActionLoadData.class);
etc...
public Action getAction(ActionEnum action)
return getAction(enumToClass.get(action));
EnumMap
非常快,所以不用担心。
【讨论】:
以上是关于在 Java 中使用 Enum 进行工厂,最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章