代码改变世界

表驱动法3

2014-05-25 14:40  ttylinux  阅读(259)  评论(0编辑  收藏  举报

需求:编写一个子程序,打印存储在一份文件中的消息。该文件有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的功能。