问题的提出
远程控制类软件的编写是个痛苦的过程,大概的思路是(假定,控制端为Client端,受控端为Server端):
1. Client端发出命令
2. Server端解析命令
3. Server端通过解析命令,执行相应的操作
4. Server处理完毕后返回处理结果
5. Client端接收处理结果
请注意Step 2,3中Server端的处理。如果所有这些都在Server端的一个过程中处理是非常可怕的事。你不得不需要一个大的Case语句,也许这样庞大且不停膨胀Case语句超越你的控制能力,逼迫你用更自由一点排比句if …then…,但这一切无疑都是一个痛苦的过程。
试想增加一项功能在Server端代价:
1. 增加一个命令解析if newCommand then newFunction;
2. 新增一个newFunction;
看起来不错,勤奋一点还算可行。但如果是团队开发,这种开发模式似乎不太容易忍受。总不能每新加一项功能,大家都要在Server端指手划脚。
问题的提出:
1. 如何才能避免因为功能增加,导致在Server端Case语句的膨胀?
2. 如何适应团队的开发?
设计思路
在同一个类中实现Client端和Server端的处理。
这样做得原因只有一个,将新增功能的处理在所属类中完成。换句话说就是将上述Server端的代价在类中完成。-“换汤不换药”?
用统一的形式表达Client端的请求和Server端的响应。
上述“换汤不换药”的苦衷,在这里希望能博得一些同情。为了解决问题1,而陷入形式主义的泥潭。好了,干巴巴的陈述只会让人感到沮丧,让我们直面代码。
TNetCommand类
源代码
// uNetCommand 为其他相关网络操作的祖先类
{{
作者:蛐蛐
时间:2004.5.24
}
unit uNetCommand;
interface
uses
Classes, IdTCPServer, IdTCPClient;
type
// TNetCommand
TNetCommand = class (TObject)
public
CommandType: Integer;??????????
RemoteCommandTime: string;
function ReadData(Client: TIdTCPClient): Boolean; virtual; abstract;
function WriteData(Server: TIdTCPServerConnection): Boolean; virtual; abstract;
end;
const
TCP_QUIT=2000;????? // 退出
TCP_NETIMAGE=3000;? // 图像操作
TCP_NETFILE=3001;?? // 文件操作
TCP_NETPROCESS=3002;? // 进程操作
TCP_NETSYSTEMINFO=3003; // 系统信息
TCP_NETEXITWINDOWS=3004;? // 退出Windows
TCP_NETKEYBOARD=3005; // 键盘操作
TCP_NETMOUSE=3006;? // 鼠标操作
implementation
end.
说明
TNetCommand类只有四个成员。CommandType用于描述Client端具体请求内容,可以想到在其子类中一定有许多关于此的常量定义。ReadData 和WriteData 两个虚函数正是我所说的“用统一的形式表达Client端的请求和Server端的响应”。
等等,uNetCommand单元中下面的一组常量是做什么用的?先看一下他的一个子类TNetImage是怎么工作的。