表驱动设计的一点见解

       昨晚看了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的实现:

          

 

ContractedBlock.gif ExpandedBlockStart.gif 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给我鼓励和意见的人.谢谢.

转载于:https://www.cnblogs.com/hrmai/archive/2008/08/16/1269318.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值