Table-Driven Design 表驱动设计
注:本文所有代码来自 http://www.codeproject.com/Articles/42732/Table-driven-Approach
在许多程序中,经常需要处理那些拥有种种色色不同特性的实体,最直接的思路是用case语句或者if-else语句处理这些不同的实体。然而,如果这类实体的数量若足够庞大,将会产生大量代码,臃肿并难以整理和维护。
先通过一对实例感受一下:
// A text adventure game
if(strcmpi(command, "north") == ) {
if(cur_location->north)
GoToLocation(cur_location->north);
else
Print("Cannot go there");
}
else if(strcmpi(command, "east") == ) {
if(cur_location->east)
GoToLocation(cur_location->east);
else
Print("Cannot go there");
}
else if(strcmpi(command, "south") == ) {
if(cur_location->south)
GoToLocation(cur_location->south);
else
Print("Cannot go there");
}
else if(strcmpi(command, "west") == ) {
if(cur_location->west)
GoToLocation(cur_location->west);
else
Print("Cannot go there");
}
相同功能的其他代码:
enum SIDE {SIDE_NORTH = , SIDE_EAST, SIDE_SOUTH, SIDE_WEST};
struct COMMAND {
const char * name;
SIDE side;
};
static const COMMAND commands[] = {
{"north", SIDE_NORTH},
{"east", SIDE_EAST},
{"south", SIDE_SOUTH},
{"west", SIDE_WEST},
};
for(int i = ; i < NUM_OF(commands); i++)
if(strcmpi(commands[i].name, command) == ) {
SIDE d = commands[i].side;
if(cur_location->sides[d])
GoToLocation(cur_location->sides[d]);
else
Print("Cannot go there");
}
从上面两段代码我们可以看出,第二段将实体从条件语句中分离出来,使得程序框架更加清晰;为了增加command names,现在只需要在一处修改代码。当数据量足够大时,可以分很方便地增添、删减或者替换,非常有利于维护。
正式定义前,再用一对代码来加强理解。(举例来自书籍《Refactoring》,Martin Fowler)
// calculating the price for renting a movie
double result = ;
switch(movieType) {
case Movie.REGULAR:
result += ;
if(daysRented > )
result += (daysRented - ) * 1.5;
break; case Movie.NEW_RELEASE:
result += daysRented * ;
break; case Movie.CHILDRENS:
result += 1.5;
if(daysRented > )
result += (daysRented - ) * 1.5;
break;
}
使用数组后的优化解决方案:
enum MovieType {Regular = , NewRelease = , Childrens = }; // Regular NewRelease Childrens
const double initialCharge[] = {, , 1.5};
const double initialDays[] = {, , };
const double multiplier[] = {1.5, , 1.5}; double price = initialCharge[movie_type];
if(daysRented > initialDays[movie_type])
price += (daysRented - initialDays[movie_type]) * multiplier[movie_type];
以上举例能非常明显的展现出表驱动设计的优点:Table-Driven代码更快、更短、更容易维护!
如果使用表驱动来整理在之前博客中写到的迷宫问题,代码最少可以简短200行!学到的太晚了!
在此给出Table-Driven Design定义:
表驱动设计是软件开发工程中的一种方法,通过从程序代码中分离的控制变量以及参数并将其存储在外部表格中的处理来简化、概括程序。主要目的在于将控制变量从程序逻辑中脱离以及着重于构建程序的模块化框架,来减轻因变更数据产生的管理工作量。
人类是智慧的,代码是伟大的!如同现实世界一样,计算机世界也有着太多东西值得我们去探索和发现!
加油吧!少年们!
大三上
2016/11/15 上午
Table-Driven Design 表驱动设计的更多相关文章
- DDD(Domain-Driven Design) 领域驱动设计
DDD(Domain-Driven Design) 领域驱动设计 1. DDD(Domain-Driven Design)是什么? DDD是Eric Evans在2003年出版的<领域驱动设计: ...
- csharp: Domain-Driven Design(领域驱动设计)
http://dddsample.sourceforge.net/ https://github.com/citerus/dddsample-core http://dddsamplenet.code ...
- (翻译)领域驱动设计实现-Implementing Domain Driven Design
简介 Implementing Domain Driven Design 领域驱动设计实现 A practical guide for implementing the Domain Driven D ...
- 领域驱动设计(DDD:Domain-Driven Design) 介绍
Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD ...
- 领域驱动设计(DDD:Domain-Driven Design) 转摘自:http://www.jdon.com/ddd.html
Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD ...
- 领域驱动设计(DDD:Domain-Driven Design)
领域驱动设计(DDD:Domain-Driven Design) Eric Evans的"Domain-Driven Design领域驱动设计"简称DDD,Evans DDD是一套 ...
- 领域驱动设计(DDD)实践之路(一)
本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/gk-Hb84Dt7JqBRVkMqM7Eg 作者:张文博 领域驱动设计(Domain Dr ...
- DDD领域驱动设计落地实践(十分钟看完,半小时落地)
一.引子 不知今年吹了什么风,忽然DDD领域驱动设计进入大家视野.该思想源于2003年 Eric Evans编写的"Domain-Driven Design领域驱动设计"简称DDD ...
- Java开发架构篇《初识领域驱动设计DDD落地》
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 DDD(Domain-Driven Design 领域驱动设计)是由Eric Eva ...
随机推荐
- proc文件系统漫谈
1. /proc/buddyinfo:/proc/buddyinfo是linuxbuddy系统管理物理内存的debug信息. 在linux中使用buddy算法解决物理内存的外碎片问题,其把所有空闲的内 ...
- pipelinedb Continuous transforms 操作
Continuous transforms 可以进行数据的转换,数据是不进行存储,主要是可以加入到其他的stream pipeline 中,或者写到其他外部 存储中,和存储过程结合使用,当前默认内置一 ...
- web 分享代码片段
<div class="bshare-custom icon-medium-plus"><a title="分享到QQ空间" class=&q ...
- mysql和redis加入到windows服务
mysql加入到windows服务: mysqld --install Mysql5.6 mysqld --remove mysql5.6 从windows的服务中删除mysql服务 net st ...
- RabbitMQ负载均衡方案之LVS
负载均衡的方案有很多,适合RabbitMQ使用的处理HAProxy之外还有LVS.LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件 ...
- RAII vs. exceptions
析构函数不能抛出异常, 原因 析构函数已经变成了异常处理的一部分 如果对象出了异常,现在异常处理模块为了维护系统对象数据的一致性,避免资源泄漏,有责任释放这个对象的资源,调用对象的析构函数,可现在假如 ...
- VS2017增加数据库连接串
新装VS2017后,按照三石提供的MVC入门教程,创建MVC应用后,能生成数据库文件(在APP_DATA目录),但无法创建连接,服务器路径一直不正确. 解决方法: 1.重新打开VS2017安装界面,选 ...
- SQLServer2008开启远程连接
1.查看sqlserver brower协议是否启动 2.对象资源管理器 右键属性->选择-> 方面->服务器配置->Remoteaccess ->True 3.对象资源 ...
- Spring Cloud 入门 之 Hystrix 篇(四)
原文地址:Spring Cloud 入门 之 Hystrix 篇(四) 博客地址:http://www.extlight.com 一.前言 在微服务应用中,服务存在一定的依赖关系,如果某个目标服务调用 ...
- php中is_null,empty,isset,unset 的区别详细介绍
is_null, empty, isset, unset 我们先来看看这4个函数的描述. isset 判断变量是否已存在(配置)unset 把变量删除(释放)掉empty 判断变量是否为空is_nul ...