请参阅下面的代码。这里基于String常量,我实例化了不同类型的组件类。现在至少有15种不同类型的String常量。因此,如果我遵循这种模式,将有15种不同的情况和那些很多if -else块。有没有更好的方法呢?我想通过尽可能少的代码更改来灵活地添加和删除案例。
public UIComponent initCellEditor(String editorType) {
UIComponent editControl = null;
if ("TbComboBoxCellType".equals(editorType)) {
editControl = new WebListEntryField();
editControl.setId("ComboBox");
} else if ("TbStringCellType".equals(editorType)) {
editControl = new WebInputEntryField();
editControl.setId("String");
} else if ("TbDateCellType".equals(editorType)) {
editControl = new WebDateEntryField();
editControl.setId("Date");
} else if ("TbDateTimeCellType".equals(editorType)) {
editControl = new WebDateTimeEntryField();
editControl.setId("DateTime");
} else {
//default editor is allways a text input
editControl = new WebInputEntryField();
editControl.setId("Input");
}
return editControl;
}
P.S:我们正在使用JDK 6。所以不能使用开启字符串功能。
答案 0 :(得分:8)
您可以将这些字符串常量转换为枚举,并在枚举上添加构建器方法,例如
public enum CellType {
TbComboBox {
@Override
public UIComponent newComponent() {
return new xxx();
}
},
TbDate {
@Override
public UIComponent newComponent() {
return new xxx();
}
}
public abstract UIComponent newComponent();
}
这种方法的优点在于它用多态性取代IFs
(在我的意见中是非常OO)。
抱歉,我刚才意识到你有一个默认类型(代码中的最后一个),所以你可能需要在某处添加if
:(。
答案 1 :(得分:4)
可能:使用Map
。只要您将新类型注入Map
,即使您创建新类,此方法也有可能工作。它有依赖注入的味道。
package cruft;
import java.util.HashMap;
import java.util.Map;
/**
* UIComponentFactory description here
* @author Michael
* @link
* @since 9/18/12 5:48 AM
*/
public class UIComponentFactory {
Map<String, UIComponent> uiComponentMap;
Map<String, String> uiIdMap;
public UIComponentFactory(Map<String, UIComponent> uiComponentMap, Map<String, String> uiIdMap) {
this.uiComponentMap = new HashMap<String, UIComponent>(uiComponentMap);
this.uiIdMap = new HashMap<String, UIComponent>(uiIdMap);
}
public UIComponent initCellEditor(String editorType) {
UIComponent editControl = null;
editControl = this.uiComponentMap.get(editorType);
if (editControl != null) {
editControl.setId(this.uiIdMap.get(editorType));
} else {
editControl = new WebInputEntryField();
editControl.setId("Input");
}
return editControl;
}
}
答案 2 :(得分:2)
您可以使用枚举:
public static enum Editor {
TB_COMBOBOX_CELL("tbComboBoxCellType", "ComboBox") {
public UIComponent getComponent() {
return new WebListEntryField();
}
},
TB_STRING_CELL("TbStringCellType", "String") {
//etc
};
private final String type;
private final String id;
private Editor(String type, String id) {
this.type = type;
this.id = id;
}
public String getType() {
return type;
}
public String getId() {
return id;
}
public abstract UIComponent getComponent();
private static Map<String, Editor> types = new HashMap<String, Editor>();
static {
for (Editor e : Editor.values()) {
types.put(e.getType(), e);
}
}
public static Editor getEditor(String type) {
Editor e = types.get(type);
if (e == null) return Editor.DEFAULT_EDITOR;
return e;
}
}
然后你的方法变成:
public UIComponent initCellEditor(String editorType) {
Editor e = Editor.getEditor(editorType);
UIComponent editControl = e.getComponent();
editControl.setId(e.getId());
return editControl;
}
答案 3 :(得分:1)
您可以使用Factory
模式根据其类型创建对象。例如:
创建一个像这样的工厂类:
public class UIComponentFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(UIComponentFactory.class);
private static UIComponentFactory instance;
private static final LinkedHashMap<String, Class> COMPONENTS_MAP = new LinkedHashMap<String, Class>() {{
put("TbComboBoxCellType", WebListEntryField.class);
put("TbStringCellType", WebInputEntryField.class);
put("TbDateCellType", WebDateEntryField.class);
}};
private UIComponentFactory() {
}
public UIComponent createUIComponent(String type) {
Class componentClass = COMPONENTS_MAP.get(type);
Object componentObject = null;
if (componentClass != null) {
try {
componentObject = componentClass.newInstance();
} catch (InstantiationException ex) {
LOGGER.error("Instantiation exception occurred", ex);
throw new SystemException("Instantiation exception occurred", ex);
} catch (IllegalAccessException ex) {
LOGGER.error("Illegal access exception occurred", ex);
throw new SystemException("Illegal access exception occurred", ex);
}
}
return (UIComponent) componentObject;
}
public static UIComponentFactory getInstance() {
if (instance == null) {
instance = new UIComponentFactory();
}
return instance;
}
}
然后创建组件使用:
UIComponentFactory factory = UIComponentFactory.getInstance();
UIComponent component = factory.createUIComponent("yourComponentType");
这比使用if else
语句更有效。
答案 4 :(得分:1)
说实话:不要改变任何东西。有几个选项可以重构此代码,但恕我直言,它们不会提高代码的可读性。坚持if
,它并不像他们想要你相信那么邪恶......
答案 5 :(得分:1)
我建议采用基于枚举的方法如下:
enum EditorType {
TbComboBoxCellType(WebListEntryField.class, "ComboBox"),
TbStringCellType(WebInputEntryField.class, "String"),
TbDateCellType(WebDateEntryField.class, "Date"),
TbDateTimeCellType(WebDateTimeEntryField.class, "DateTime"),
Generic(WebInputEntryField.class, "Input");
private final Class<? extends UIComponent> componentType;
private final String id;
private EditorType(Class<? extends UIComponent> componentType, String id) {
this.componentType = componentType;
this.id = id;
}
public static UIComponent createComponent(String editorType) {
EditorType type;
try {
type = valueOf(editorType)
} catch (IllegalArgumentException e) {
type = Generic;
}
return type.createComponent();
}
public UIComponent createComponent() {
try {
UIComponent component = componentType.newInstance();
component.setId(id);
return component;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
答案 6 :(得分:0)
您不应每次都创建new WebListEntryField();
或其他xxEntryField()
。创建一个私有字段并返回相同的实例。
答案 7 :(得分:0)
另一种选择是使用枚举来捕获所有
CellTypes
和另一个或相同的枚举来获得ID 并使用该枚举来比较输入的输入。
答案 8 :(得分:0)
在枚举上使用开关。将String editorType
更改为emum类型。如果无法做到这一点,请将editorType
转换为枚举,如following SO question。
答案 9 :(得分:0)
您可以使用基于枚举的比较。为不同的输入类型创建不同的枚举,然后使用switch case。
EditorType.java
public enum EditorType {
COMBO_CELL_TYPE("TbComboBoxCellType"),
STRING_CELL_TYPE("TbStringCellType"),
DATE_CELL_TYPE("TbDateCellType"),
TIME_CELL_TYPE("TbDateCellType"),
INPUT_CELL_TYPE("TbInputCellType");
public String value;
private EditorType(String value) {
this.value = value;
}
}
比较使用switch语句。
public UIComponent initCellEditor(EditorType editorType) {
UIComponent editControl = null;
switch (editorType) {
case COMBO_CELL_TYPE:
// logic here
break;
case STRING_CELL_TYPE:
break;
case DATE_CELL_TYPE:
break;
case TIME_CELL_TYPE:
break;
default:
// default logic
}
}