随笔-42  评论-306  文章-11  trackbacks-4
上回说到Command的雏形被高手改过之后,高手让我再对代码进行一下重构和完善,并且还特意嘱咐不要出现那么多的字符串。饿滴神啊,该怎么办呢?
外事不决问Google,果然,有办法了:
我用一个配置文件,把用户输入的命令和实际的Command类一一对应,然后利用反射实例化这个类。
好,那就开始做吧。
首先创建app.config文件,这个是工程默认会读取的,就不用自己解析XML了,这个文件里面是这样的:
Code

指令跟对应的类是一一对应的,然后再创建一个Class,用来读取配置文件,生成对应的实例,这个类起什么名字好呢?
它会生成很多不同类型的实例,好,暂且就叫它CommandFactory吧,然后给它一个静态方法,一个参数,返回值就是ICommand。
Code

我都有点儿佩服我自己了,一个很好的解决办法,嗯,厉害!!!
Processor类也需要修改,以前是只能添加新的Command,但是如果用户第二次输入同样指令,就不应该添加,而应该是替换了。
到现在,最终的主方法已经是这样子的了:
Code

比以前简洁了不少,而且每那么多的if else 和常量了,我的工作完成了。

高手看我沾沾自喜的样子,走过来,说:做完了,我看看。
看了一眼,又说:你比我当年不差啊,看过设计模式,是吧。
我老老实实的说:没看过,我就是觉得这么做应该就是比较好的做法,也不知道什么模式不模式的。
高手自言自语:是啊,你不受GOF设计模式的束缚,不强迫自己往他给定的UML类图上靠,而思想上却是相通的,小伙儿有前途啊。
听了高手这一顿白话,我信心倍增。
高手看我信心爆膨,说:别高兴的太早,刚才客户又有新的需求了,这回看你能不能瞎猫碰到死耗子身上,给我整出来。
我说:没问题。
不过,过了三分钟,我满面愁容的坐在电脑前,不知道如何下手。

代码:http://files.cnblogs.com/game-over/Command2.rar
Tag标签: 设计模式
posted on 2008-02-27 20:33 Game_over 阅读(1861) 评论(9)  编辑 收藏

评论:
#1楼  2008-02-28 04:02 | saucer [未注册用户]
感觉最后的代码还是不够干净,或者说其中的语句的抽象层次不一致,大概应该这样

while (true)
{
//get input
//process input to return normalized CommandName and arguments
//get a command object based CommandName
//Execute the command object with the arguments
}

大概的实现:

interface ICommand
{
void Execute(params object[] parameters);
}

....
class EchoCommand : ICommand
{
void Execute(params object[] parameters)
{
foreach(object o in parameters)
Console.WriteLine(o);
}
}

class ExitCommand : ICommand
{
void Execute(params object[] parameters)
{
Environment.Exit(-1);
}
}

....
这二个类使用你的配置文件来处理命令和取得ICommand对象,也许应该合二为一,分成2个是因为两者的职责不同,虽然都依赖于配置文件中的同个配置

static class InputProcessor
{
public static void GetCommand(string input, out string commandName, out object[] parameters)
{
//根据配置文件里设置的命令,得到规范的commandName,并且把剩余的字符串变成参数,object[] parameters?还是应该是string [] parameters?
}

//如果更复杂的话,也许应该改成非静态类,从配置文件中获得一个InputProcessingStrategy对象,传入构造器,负责怎么把用户的输入转换成一个命令和一堆参数

}

static class CommandFactory
{
public static ICommand GetCommand(string commandName)
{
//根据配置文件里和commandName转换成ICommand对象
}
}

客户端代码:

string input,commandName;
object[] parameters;
while (true)
{
input = Console.ReadLine();
InputProcessor.GetCommand(input, out commandName, out parameters);
ICommand cmd = CommandFactory(commandName);
cmd.Execute(parameters);
}

这么做的话,如果要增加一个Command,你只要新建一个Command对象,更新配置文件即可
  回复  引用    
#2楼  2008-02-28 04:03 | saucer [未注册用户]
ICommand cmd = CommandFactory.GetCommand(commandName);

  回复  引用    
#3楼  2008-02-28 07:00 | 金色海洋(jyk)      
喜欢 “是啊,你不受GOF设计模式的束缚,不强迫自己往他给定的UML类图上靠,而思想上却是相通的,小伙儿有前途啊。”这一句,其他的还没有看呢
  回复  引用  查看    
#4楼  2008-02-28 08:47 | henryfan [未注册用户]
String command = "";
Processor p = new Processor();
string[] arges = null;
while (true)
{
command = Console.ReadLine();
arges= command.Split(SPACE.ToCharArray())[0];
ICommand cmd = CommandFactory.getCommand(arges[0]);
if (arges.length==1)
{
cmd.setRequest(arges[0]);
}
else
{
cmd.setRequest(arges[1]);
}

p.setCommand(arges[0], cmd);
p.request();
}
  回复  引用    
#5楼 [楼主] 2008-02-28 08:49 | Game_over      
@saucer
您说的很好,抽象层次不一致,说得好。
我也说说我的想法:
我觉得是对指令进行统一管理比较好,这样可以在以后增加比较复杂的控制。

我之前没想好参数应该怎么传递,您提出的InputProcessingStrategy可以解决这个问题了,谢谢。

代码还需要再整理。
  回复  引用  查看    
#6楼  2008-02-28 10:10 | Intermapper [未注册用户]
的确很干净,比我强多了!向你学习!
  回复  引用    
#7楼  2008-02-28 12:24 | fengfeng [未注册用户]
写的不错,期待下文.
  回复  引用    
#8楼  2008-02-28 12:35 | 金色海洋(jyk)      
这个和我的那个接收短信的问题挺像的。

http://www.cnblogs.com/jyk/archive/2008/01/15/1040413.html

msgRecv = (HBS.SMSReceive.MessageReceive)Assembly.Load("HBS.SMSReceive").CreateInstance("HBS.SMSReceive.MessageOperation" + msg[0].Trim()); // msg[0].Trim() 相当于 “echo”

if (msgRecv == null)
{
//没有找到对应的分析短消息的类,设置默认选项
msgRecv = new HBS.SMSReceive.MessageOperationOther();
}


//处理接收到的短消息
re = msgRecv.SaveMsg(Mobile,dr["ArriveTime"].ToString(),dr["Msg"].ToString().Trim().Replace(" "," ")); // 类似于 cmd.setRequest


HBS.SMSReceive.MessageReceive 就简单多了,一个基类 多个子类,形成了多态的形式。一个子类就是一种短信(命令)
我的帖子里有详细的代码。



  回复  引用  查看    
#9楼  2008-02-28 16:23 | zzz [未注册用户]
interface ICommand<T>
{
void Execute(params T[] parameters);
}

....
class EchoCommand<T> : ICommand<T>
{
void Execute(params T[] parameters)
{
foreach(T o in parameters)
Console.WriteLine(o);
}
}


public static T GetInstance<T>(string className)
{
T instance;
if (!string.IsNullOrEmpty(className))
{
Type type = Type.GetType(className);
instance = (T)Activator.CreateInstance(type);
}
else
{
instance = default(T);//引用类型默认值null
}
return instance;
}

public static ICommand GetCommand<ICommand>(string commandName)
{
return GetInstance<ICommand>(ConfigurationSettings.AppSettings[commandName]);
}

泛型不是更好一点
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: