设计模式循序渐进(6)命令模式 command

模式解说:
  命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
  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 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.

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.
posted @ 2008-06-13 16:33  treemon  阅读(460)  评论(2编辑  收藏  举报