需求:编写一个子程序,打印存储在一份文件中的消息。该文件有500条消息,有20种不同类型的消息。
思路:将消息逐条读入,然后,解释该消息,看它是属于哪种类型的,然后,调用针对该类型的打印程序。如此,实现方式,有:1.要写20个if语句,来判断该消息是属于哪种类型;
然后,还需要20个打印子程序。当然,还可以采用继承的方式,写一个抽象类,该抽象类抽象了20种不同类型的消息特征,然后,具体的消息类型是该抽象类的一个子类;但是,
同样要判断该消息类型,同样是要有20个if语句,然后,再实例化相应的子类。
采用表驱动法的思路:一条消息的消息类型,作为Key,在一个消息类型表中找到该消息类型的描述,这是直接查询表,得到该消息的消息类型描述。然后,写一个通用的打印子程序来打印消息。
假如这20种不同类型的消息,它们的特征是这样的:
类型ID;类型描述 |
平均温度;浮点数值 |
温度范围;浮点数值 |
采样点数;整数值 |
测量时间;时间值 |
一条消息,有个头部;然后是每个消息项,一个消息项,由两部分组成,一个是该消息项的名称,一个是该消息项的值类型。
那么,其通用打印子程序就是:
输出一个名称,然后,输出一个数值。
输出名称,这个可以从其对应的消息类型描述中取到;然后根据值类型,调用对应的值类型打印子程序。
如此,某个消息类型改变的时候,假设没有增加新的值类型,那么,也就只需要修改该消息类型的描述,也就是增加一个消息项的名称+消息项的值类型。
即使,增加了一个新的值类型,那么只需要增加一个新的值类型的打印子程序。
整个实现流程:
1.读入一条消息,根据消息的头部类型ID,然后,查表,得到它的类型描述信息。----表驱动法的应用,消除了20个if语句。
2.调用通用打印子程序,一条消息内容3作为输入参数。
通用打印程序:
2.1读出该消息的每个消息项(循环,因为一条消息究竟有多少个消息项是不确定的),然后,读出该消息项的值类型,根据值类型,调用对应的值类型打印子程序。
打印消息项的名称+打印该项的值。
下面为了演示,对内容作了以下限定:
1.消息类型,只有3种。
2.值类型,只有4种。
3.读入的消息条数,只有3条。
import java.util.ArrayList; import java.util.HashMap; import javaProblem.ComplicatedTable.ValueType; public class ComplicatedTable { private HashMap<MessageType, Object> messageTypeTable = new HashMap<MessageType, Object>(); public static enum MessageType { TypeOne, TypeTwo, TypeThree } public enum ValueType { FloatingPoint, IntegerType, TimeOfDay, StringType } public static final String IDKey = "IDKey"; public static final String ItemsKey = "ItemsKey"; public void addNewType(HashMap<String, Object> oneType) { messageTypeTable.put((MessageType) oneType.get(IDKey), oneType); } public void commonDisplay(HashMap<String, Object> one, TypeUtil util) { @SuppressWarnings("unchecked") HashMap<String, Object> messageDescrip = (HashMap<String, Object>) messageTypeTable .get(one.get(ComplicatedTable.IDKey)); @SuppressWarnings("unchecked") ArrayList<String> values = (ArrayList<String>) one .get(ComplicatedTable.ItemsKey); ArrayList<ItemDescrip> itemsDescrip = (ArrayList<ItemDescrip>) messageDescrip .get(ComplicatedTable.ItemsKey); for (int i = 0; i < values.size(); i++) { ItemDescrip oneItem = itemsDescrip.get(i); String value = values.get(i); switch (oneItem.getValueType()) { case FloatingPoint: util.displayFLoatPoint(value, oneItem.getLable()); break; case IntegerType: util.displayInteger(value, oneItem.getLable()); break; case TimeOfDay: util.displayTimeOfDay(value, oneItem.getLable()); break; case StringType: util.displayString(value, oneItem.getLable()); break; } } } public static void main(String[] args) { TypeUtil util = new TypeUtil(); ComplicatedTable oneTable = new ComplicatedTable(); oneTable.addNewType(util.initalTypeOne()); oneTable.addNewType(util.initalTypeTwo()); oneTable.addNewType(util.initalTypeThree()); ArrayList<HashMap<String, Object>> messages = new ArrayList<HashMap<String, Object>>(); // 模拟从文件中读出的数据 HashMap<String, Object> oneMessage = new HashMap<String, Object>(); ArrayList<String> itemsOne = new ArrayList<String>(); itemsOne.add("43.3"); itemsOne.add("高温"); oneMessage.put(ItemsKey, itemsOne); oneMessage.put(IDKey, MessageType.TypeOne); messages.add(oneMessage); HashMap<String, Object> twoMessage = new HashMap<String, Object>(); ArrayList<String> itemsTwo = new ArrayList<String>(); itemsTwo.add("中国"); itemsTwo.add("13"); twoMessage.put(ItemsKey, itemsTwo); twoMessage.put(IDKey, MessageType.TypeTwo); messages.add(twoMessage); HashMap<String, Object> threeMessage = new HashMap<String, Object>(); ArrayList<String> itemsThree = new ArrayList<String>(); itemsThree.add("2012-04-30"); itemsThree.add("13"); threeMessage.put(ItemsKey, itemsThree); threeMessage.put(IDKey, MessageType.TypeThree); messages.add(threeMessage); // 读入消息,然后打印消息;通过采用表驱动法,消除了if判断 for (int i = 0; i < messages.size(); i++) { oneTable.commonDisplay(messages.get(i), util); } } } class ItemDescrip { private String Label; private ValueType valueType; public void setDescrip(String label, ValueType valueType) { this.Label = label; this.valueType = valueType; } public String getLable() { return Label; } public ValueType getValueType() { return valueType; } }
//------
import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import javaProblem.ItemDescrip; import javaProblem.ComplicatedTable.MessageType; import javaProblem.ComplicatedTable.ValueType; public class TypeUtil { public HashMap<String, Object> initalTypeOne() { HashMap<String, Object> typeOne = new HashMap<String, Object>(); typeOne.put(ComplicatedTable.IDKey, MessageType.TypeOne); ArrayList<ItemDescrip> items = new ArrayList<ItemDescrip>(); ItemDescrip one = new ItemDescrip(); one.setDescrip("Average_temperature", ValueType.FloatingPoint); items.add(one); ItemDescrip two = new ItemDescrip(); two.setDescrip("Temperature_alias", ValueType.StringType); items.add(two); typeOne.put(ComplicatedTable.ItemsKey, items); return typeOne; } public HashMap<String, Object> initalTypeTwo() { HashMap<String, Object> typeTwo = new HashMap<String, Object>(); ArrayList<ItemDescrip> items = new ArrayList<ItemDescrip>(); typeTwo.put(ComplicatedTable.IDKey, MessageType.TypeTwo); ItemDescrip one = new ItemDescrip(); one.setDescrip("Location", ValueType.StringType); items.add(one); ItemDescrip two = new ItemDescrip(); two.setDescrip("Amount", ValueType.IntegerType); items.add(two); typeTwo.put(ComplicatedTable.ItemsKey, items); return typeTwo; } public HashMap<String, Object> initalTypeThree() { HashMap<String, Object> typeThree = new HashMap<String, Object>(); typeThree.put(ComplicatedTable.IDKey, MessageType.TypeThree); ArrayList<ItemDescrip> items = new ArrayList<ItemDescrip>(); ItemDescrip one = new ItemDescrip(); one.setDescrip("Day", ValueType.TimeOfDay); items.add(one); ItemDescrip two = new ItemDescrip(); two.setDescrip("Amount", ValueType.IntegerType); items.add(two); typeThree.put(ComplicatedTable.ItemsKey, items); return typeThree; } public void displayFLoatPoint(String value, String label) { // 对应的其它格式化措施 System.out.println(label + "; value:" + value); } public void displayInteger(String value, String label) { // 其它格式化措施 System.out.println(label + "; value:" + value); } public void displayString(String value, String label) { // 对应的其它格式化措施 System.out.println(label + "; value:" + value); } public void displayTimeOfDay(String value, String label) { // 对应的其它格式化措施 System.out.println(label + "; value:" + value); } }
运行的输出结果:
Average_temperature; value:43.3
Temperature_alias; value:高温
Location; value:中国
Amount; value:13
Day; value:2012-04-30
Amount; value:13
如此,在有新的消息类型的时候,只要往TypeUtil中添加新的消息类型描述便可;如果有新的值类型,同样只要往TypeUtil中添加新的打印子程序便可。
当然,还可以再继续优化。优化到,对外提供一个添加消息类型的接口,然后,用户只要添加新的消息类型;然后,自己也可以实现自己要打印的消息子程序。
--------总之,本文,再次展示,采用表驱动法来消除if的功能。