设计模式循序渐进(6)命令模式 command
模式解说:
命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
Comnand模式的思想是把命令封装在一个类中,就是这里的ICommand接口,同时把接收对象也封装在一个类中就是这里的TReceiver类中,由调用这个命令的类祈求者TInvoker类来调用。
Comnand模式和面向过程的回调函数是一样的,注册回调函数和为具体的命令对象设置接受者对象相似,采用Command模式对命令的发出者和命令的执行者进行了解耦。
UML结构图
命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
Comnand模式的思想是把命令封装在一个类中,就是这里的ICommand接口,同时把接收对象也封装在一个类中就是这里的TReceiver类中,由调用这个命令的类祈求者TInvoker类来调用。
Comnand模式和面向过程的回调函数是一样的,注册回调函数和为具体的命令对象设置接受者对象相似,采用Command模式对命令的发出者和命令的执行者进行了解耦。
UML结构图
// Added by zhangsk 2008-6-13 14:47:40 command模式学习
unit uCommand;
interface
uses
SysUtils;
type
TReceiver = class(TObject) //接受者,相当于实现回调的具体功能;
public
procedure Action;
end;
ICommand = interface //命令接口
['{062332DB-F4A4-435B-98E3-3E05E7ADBDEF}']
procedure SetReceiver(const Value: TReceiver);
procedure Execute; //执行命令
end;
TInvoker = class(TObject) //祈求者,客户端直接调用祈求者
private
FCommand: ICommand; //维护一个具体命令
procedure SetCommand(const Value: ICommand);
public
property Command: ICommand read FCommand write SetCommand; //设置具体命令
procedure Invoker; //客户端操作祈求者的具体方法;
end;
TConcreteCommand = class(TInterfacedObject, ICommand) //具体命令
private
FReceiver: TReceiver;
public
procedure SetReceiver(const Value: TReceiver);
procedure Execute; //具体命令执行的实现
end;
implementation
{ TInvoker }
procedure TInvoker.Invoker;
begin
if Supports(FCommand, ICommand) then
FCommand.Execute;
end;
procedure TInvoker.SetCommand(const Value: ICommand);
begin
FCommand := Value;
end;
{ TConcreteCommand }
procedure TConcreteCommand.Execute;
begin
if Assigned(FReceiver) then //相当实现了一个回调;TCommand.Execute回调TReceiver.Action
FReceiver.Action;
Writeln('Command By TConcreteCommand.Execute');
end;
{ TReceiver }
procedure TReceiver.Action;
begin
Writeln('TReceiver.Action');
end;
procedure TConcreteCommand.SetReceiver(const Value: TReceiver);
begin
FReceiver := Value;
end;
end.
unit uCommand;
interface
uses
SysUtils;
type
TReceiver = class(TObject) //接受者,相当于实现回调的具体功能;
public
procedure Action;
end;
ICommand = interface //命令接口
['{062332DB-F4A4-435B-98E3-3E05E7ADBDEF}']
procedure SetReceiver(const Value: TReceiver);
procedure Execute; //执行命令
end;
TInvoker = class(TObject) //祈求者,客户端直接调用祈求者
private
FCommand: ICommand; //维护一个具体命令
procedure SetCommand(const Value: ICommand);
public
property Command: ICommand read FCommand write SetCommand; //设置具体命令
procedure Invoker; //客户端操作祈求者的具体方法;
end;
TConcreteCommand = class(TInterfacedObject, ICommand) //具体命令
private
FReceiver: TReceiver;
public
procedure SetReceiver(const Value: TReceiver);
procedure Execute; //具体命令执行的实现
end;
implementation
{ TInvoker }
procedure TInvoker.Invoker;
begin
if Supports(FCommand, ICommand) then
FCommand.Execute;
end;
procedure TInvoker.SetCommand(const Value: ICommand);
begin
FCommand := Value;
end;
{ TConcreteCommand }
procedure TConcreteCommand.Execute;
begin
if Assigned(FReceiver) then //相当实现了一个回调;TCommand.Execute回调TReceiver.Action
FReceiver.Action;
Writeln('Command By TConcreteCommand.Execute');
end;
{ TReceiver }
procedure TReceiver.Action;
begin
Writeln('TReceiver.Action');
end;
procedure TConcreteCommand.SetReceiver(const Value: TReceiver);
begin
FReceiver := Value;
end;
end.
unit uClient;
interface
uses
uCommand;
type
TClient = class(TObject)
private
FReceiver: TReceiver;
FCommand: ICommand;
FInvoker: TInvoker;
public
constructor Create;
destructor Destroy; override;
procedure TestCommand;
end;
implementation
{ TClient }
constructor TClient.Create;
begin
inherited Create;
FReceiver := TReceiver.Create;
FCommand := TConcreteCommand.Create;
FInvoker := TInvoker.Create;
FInvoker.Command := FCommand;
FCommand.SetReceiver(FReceiver);
end;
destructor TClient.Destroy;
begin
if Assigned(FReceiver) then //client创建了FReceiver,所以要client来释放
begin
FReceiver.Free;
FReceiver := nil;
end;
//FCommand是接口自己通过引用计数释放。
if Assigned(FInvoker) then
begin
FInvoker.Free;
FInvoker := nil;
end;
inherited Destroy;
end;
procedure TClient.TestCommand;
begin
FInvoker.Invoker;
end;
end.
interface
uses
uCommand;
type
TClient = class(TObject)
private
FReceiver: TReceiver;
FCommand: ICommand;
FInvoker: TInvoker;
public
constructor Create;
destructor Destroy; override;
procedure TestCommand;
end;
implementation
{ TClient }
constructor TClient.Create;
begin
inherited Create;
FReceiver := TReceiver.Create;
FCommand := TConcreteCommand.Create;
FInvoker := TInvoker.Create;
FInvoker.Command := FCommand;
FCommand.SetReceiver(FReceiver);
end;
destructor TClient.Destroy;
begin
if Assigned(FReceiver) then //client创建了FReceiver,所以要client来释放
begin
FReceiver.Free;
FReceiver := nil;
end;
//FCommand是接口自己通过引用计数释放。
if Assigned(FInvoker) then
begin
FInvoker.Free;
FInvoker := nil;
end;
inherited Destroy;
end;
procedure TClient.TestCommand;
begin
FInvoker.Invoker;
end;
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
uCommand in 'uCommand.pas',
uClient in 'uClient.pas';
var
client: TClient;
begin
{ TODO -oUser -cConsole Main : Insert code here }
client := TClient.Create;
client.TestCommand;
client.Free;
Readln;
end.
{$APPTYPE CONSOLE}
uses
SysUtils,
uCommand in 'uCommand.pas',
uClient in 'uClient.pas';
var
client: TClient;
begin
{ TODO -oUser -cConsole Main : Insert code here }
client := TClient.Create;
client.TestCommand;
client.Free;
Readln;
end.