昨晚看了CC2的一章,专门讲表驱动设计的.看了两三次才看懂了.然后想起了一起自己做过的一个项目的那种劣质实现胆战心惊,真是相逢恨晚呀.
以前做过的一个项目是从一个文本框中输入一个日期,然后判断这个日期是否合法,我当时的想法是判断输入的年份是不是闰年,然后再判断输入的月份是不是二月,如果是二月再判断有没有超出日期.是不是很晕....如果我们用表驱动那么我们应该得到一下的一个很简单的实现:
定义一个二维数组dayNumber[2][12]其中dayNumber[0]保存一般的非闰年的月份日数,dayNumber[1]保存闰年的月份日数.然后我们只要定义一个函数int IsLeapYear(int year)是闰年就返回一个1不是返回0,那么对于每一个月份的最大日数我们都可以这样子得到了lastDay=dayNumber[isLeapYear(year)][month],没有长长的If语句.
而在后面CC2上给出了一个更加复杂的例子.这个例子是这样子的:
有很多记录文件,每一个记录文件记录着500条数据,在这些数据中共有20中不同的数据形式.然后每一条数据都由一些field组成,每一种field的计算机表现形式不同.最后,每一种数据的数据组成方式可能会改变,由客户决定.现在我们要将数据里面的内容读出来显示在屏幕上.我们会怎么样做了?
我们如果按照面向对象的我们就会写一个抽象的Message来作为每一中数据形式的基类,然后再继承,派生.可是要是用户再增加类的数目了?
再CC2里面介绍了用表驱动法来解决这个问题,我们可以定义一个AbstractField的基类来代表所有的field类型,然后就每一个具体的Field类型写一个实现类.再定义一个代表各种field类型的枚举.最后定义一个Message类代表每一个数据,和定义一个AbstractField类型的数组,数组的内容有每一种Field类型的实例组成.最后对于每一条数据我们都有一下的一种表达方式:
for each field in message
fields[fieldtype].Print(str)
我们根本上就不用用逻辑判断去实现这个功能.
下面我给出一个.net的实现:
Code
class Program
{
private static AbstractField[] array = new AbstractField[] { new IntField(), new ObjField(), new StrField() };
static void Main(string[] args)
{
Message m = new Message();
m.AddFieldToMessage(FieldType.IntegerField, "10000");
m.AddFieldToMessage(FieldType.ObjectField, "object");
m.AddFieldToMessage(FieldType.StringField, "string");
List<field> fields = m.GetFields();
int count = fields.Count;
int index = 0;
while (index < count)
{
array[(int)fields[index].type].PrintMessageField(fields[index].body);
index++;
}
Console.Read();
}
}
class Message
{
private List<field> fields;
public void AddFieldToMessage(FieldType type, string body)
{
field addField = new field();
addField.body = body;
addField.type = type;
fields.Add(addField);
}
public List<field> GetFields()
{
return fields;
}
public Message()
{
fields = new List<field>();
}
}
abstract class AbstractField
{
public virtual void PrintMessageField(string body)
{
throw new Exception("this method must be implement");
}
}
class IntField : AbstractField
{
public override void PrintMessageField(string body)
{
Console.WriteLine("print from IntField:{0}", body);
//base.PrintMessageField(body);
}
}
class StrField : AbstractField
{
public override void PrintMessageField(string body)
{
Console.WriteLine("Print from strField:{0}", body);
//base.PrintMessageField(body);
}
}
class ObjField : AbstractField
{
public override void PrintMessageField(string body)
{
Console.WriteLine("Print from objField:{0}", body);
//base.PrintMessageField(body);
}
}
enum FieldType : int
{
IntegerField = 0,
StringField,
ObjectField
}
struct field
{
public FieldType type;
public string body;
}
这是我的实现,水平有限,有什么不对的请指正.
最后谢谢所有上我的blog给我鼓励和意见的人.谢谢.