insideVCL书中提到的两个设计模式:dispatcher和broadcasting

下面是按照书中例子写的:

首先是TDispatcher类,负责储存所有处理消息的方法

unit untDispatcher;

interface

uses
  Messages;

const

  MY_BASE = $BE00;
  MY_MSG1 = MY_BASE + 01;
  MY_MSG2 = MY_BASE + 02;

type
  TMessageHandler = procedure (var aMessage: Tmessage) of object;

  TDispatcher = class
    private
      Handles: array[0..100] of TMessageHandler;

      function GetBaseIndex(const iMessageID: Integer): Integer;
      procedure DoAddHandler(const iMessageID: Integer; aHandle: TMessageHandler);

    public
      constructor create;
      procedure SendMessage(var aMessage: TMessage);
      function AddHandle(const iMessageID: Integer; aHandle: TMessageHandler): Integer;
  end;

implementation

{ TDispatcher }

function TDispatcher.AddHandle(const iMessageID: Integer; aHandle: TMessageHandler): Integer;
begin
  Result := GetBaseIndex(iMessageID);
  if Result <> -1 then
    DoAddHandler(Result, aHandle);
end;

constructor TDispatcher.create;
var
  I: Integer;
begin
  for I := 0 to 100 do
  begin
    Handles[I] := nil;
  end;
end;

procedure TDispatcher.DoAddHandler(const iMessageID: Integer; aHandle: TMessageHandler);
begin
  Handles[iMessageID] := aHandle;
end;

function TDispatcher.GetBaseIndex(const iMessageID: Integer): Integer;
begin
  Result := iMessageID - My_BASE;
end;

procedure TDispatcher.SendMessage(var aMessage: TMessage);
var
  msgHdl: TMessageHandler;
begin
  msgHdl := Handles[GetBaseIndex(aMessage.Msg)];
  if Assigned(msgHdl) then
    msgHdl(aMessage);
end;

end.

下面是主窗体,其中MyHandles里随便定义了两个消息方法,通过点击按钮btnOK将这两个方法以及所对应的消息,储存在FDispatcher里。最后点击按钮1和按钮2,查看消息的处理结果。

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, untDispatcher;

type
  MyHandles = class
    public
      procedure MyHandle1(var aMessage: TMessage);
      procedure MyHandle2(var aMessage: TMessage);
  end;

  TMainForm = class(TForm)
    btnOK: TButton;
    mm: TMemo;
    btnMsg1: TButton;
    btnMsg2: TButton;
    procedure btnOKClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnMsg1Click(Sender: TObject);
    procedure btnMsg2Click(Sender: TObject);
  private
    { Private declarations }
    FDispatcher: TDispatcher;
    FMyHandles: MyHandles;
  public
    { Public declarations }
    procedure AddMm(const s: string);
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

{ TMainForm }

procedure TMainForm.AddMm(const s: string);
begin
  mm.Lines.Add(s);
end;

{ MyHandles }

procedure MyHandles.MyHandle1(var aMessage: TMessage);
begin
  MainForm.AddMm('aaaaaaaaaaa1');
end;

procedure MyHandles.MyHandle2(var aMessage: TMessage);
begin
  MainForm.AddMm('bbbbbbbbbbbb2');
end;

procedure TMainForm.btnMsg1Click(Sender: TObject);
var
  aMessage: TMessage;
begin
  FillChar(aMessage, SizeOf(tmessage), 0);
  aMessage.Msg := MY_MSG1;
  FDispatcher.SendMessage(aMessage);
end;

procedure TMainForm.btnMsg2Click(Sender: TObject);
var
  aMessage: TMessage;
begin
  FillChar(aMessage, SizeOf(tmessage), 0);
  aMessage.Msg := MY_MSG2;
  FDispatcher.SendMessage(aMessage);
end;

procedure TMainForm.btnOKClick(Sender: TObject);
begin
  FDispatcher.AddHandle(MY_MSG1, FMyHandles.MyHandle1);
  FDispatcher.AddHandle(MY_MSG2, FMyHandles.MyHandle2);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FDispatcher := TDispatcher.create;
  FMyHandles := MyHandles.Create;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FDispatcher);
  FreeAndNil(FMyHandles);
end;

end.

下面是程序运行结果:

这是dispatcher,还有broadcast模式,两者结合的话,对消息处理的处理,能发挥的能量更大。比如一个产品主窗体,上面贴着很多窗体,这些窗体都继承自一个基类比如XXForm,XXForm实现了broadcast方法,其中有调用Dobroadcast(虚方法,方便子类重写处理一些业务),然后循环所有包含的窗体执行相同的操作。而在Dobroadcast中,可以使用dispatcher模式,进行消息的处理。这样可以大大减少消息在VCL中的处理流程,加快处理速度。但这种方式,适合处理自定义消息非常多的产品,如果是windows消息或者VCL中的消息,以VCL framework一秒钟执行好几万条消息的处理速度,大可不必这么麻烦。

procedure TXXForm.Broadcast(const AMessage: TMessage; var AHandled: Boolean);
var
  I: Integer;
begin
  DoBroadcast(AMessage, AHandled);
  if AHandled then Exit;
  for I := 0 to GetItemCount - 1 do
  begin
    GetItems(I).Broadcast(AMessage, AHandled);
    if AHandled then Break;
  end;
end;
以上纯属个人愚见。。。有啥不足,欢迎指正^_^


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值