使用Observer模式设计信息更新功能

来源:互联网 发布:linux memmap 编辑:程序博客网 时间:2024/04/30 12:44

    在一个软件项目中,有一个这样的需求,软件首页列出待处理消息的个数,点击进入处理窗体,处理后,刷新首页的消息个数。从软件设计来说,消息处理类并不需要知道是哪里需要刷新,可以是首页,也可以是别的地方,或者同时多个地方。因此打算采用Observer模式。

先设计出类图:

TMsg是消息处理类,它通过LoadMsgs得到待处理消息,RegisteNewMsg方法注册观察者,UnregisterNewMsg移除观察者,现在消息处理后,能及时通知观察者进行更新了。

{-----------------------------------------------------------------------------

 Unit Name: untMsgs

 Author:    bohe

 Purpose:

 History:

-----------------------------------------------------------------------------}

 

 

unit untMsgs;

 

interface

 

uses

  SysUtils, Windows, Messages, Classes, Graphics, Controls, MstProxyObj,

  Forms, Dialogs, DBClient, variants, contnrs, StdCtrls;

 

type

  TMsg = class(TObject)

  private

    FReadedMsgCount: Integer;

    FNewMsgCount: Integer;

    fSenderCode: string;

    fcdsNewMsg: TClientDataSet;

    fcdsReadedMsg: TClientDataSet;

    function GetAllMsgCount: Integer; virtual;

    procedure SetNewMsgCount(Value: Integer); virtual;

    //function GetvAllMsgData: OleVariant;

    function GetvNewMsgData: OleVariant;

    function GetvReadedMsgData: OleVariant;

  protected

    fAllMsgCount: integer;

    //fcdsMsg: TClientDataSet;

    fEduMstObj: TMstEduProxyObj;

    vMsgData: OLEVariant;

    FNewMsgReaderList: TObjectList;

    FReadedMsgReaderList: TObjectList;

    //property cdsMsg: TClientDataSet read fcdsMsg;

    procedure NotifyChange(ReaderList: TObjectList; Value: integer);

  public

    property vNewMsgData: OleVariant read GetvNewMsgData;

    //property vAllMsgData: OleVariant read GetvAllMsgData;

    property vReadedMsgData: OleVariant read GetvReadedMsgData;

 

    constructor Create(sSenderCode: string; EduMstObj: TMstEduProxyObj);

    destructor Destroy;

    procedure LoadMsgs; virtual; abstract;

    property AllMsgCount: Integer read GetAllMsgCount;

    property NewMsgCount: Integer read FNewMsgCount; //write SetNewMsgCount;

    property ReadedMsgCount: Integer read FReadedMsgCount;

    procedure RegisterNewMsg(Reader: TCustomLabel);

    procedure RegisterReadedMsg(Reader: TCustomLabel);

    procedure UnregisterNewMsg(Reader: TCustomLabel);

    function GetMsgCode(MsgID: integer): integer;

    procedure SetMsgReaded(MsgID: integer);

  end;

 

  TBurMsg = class(TMsg)

  public

    procedure LoadMsgs; override;

  end;

 

  TSchMsg = class(TMsg)

  public

    procedure LoadMsgs; override;

  end;

 

var

  SchMsg: TSchMsg;

  BurMsg: TBurMsg; 

 

implementation

 

uses DB, untConst;

 

{

*************************************TMsg*********************************

}

constructor TMsg.Create(sSenderCode: string; EduMstObj: TMstEduProxyObj);

begin

  fEduMstObj := EduMstObj;

  fSenderCode := sSenderCode;

  //fcdsMsg := TClientDataSet.Create(nil);

  fcdsNewMsg := TClientDataSet.Create(nil);

  fcdsReadedMsg := TClientDataSet.Create(nil);

  vMsgData := null;

  FNewMsgReaderList := TObjectList.Create;

  FNewMsgReaderList.OwnsObjects := false;

  FReadedMsgReaderList := TObjectList.Create;

  FReadedMsgReaderList.OwnsObjects := false;

  LoadMsgs;

end;

 

destructor TMsg.Destroy;

begin

  //fcdsMsg.close;

  //fcdsMsg.Free;

  //fcdsNewMsg.Close;

  fcdsNewMsg.Free;

  fcdsReadedMsg.Free;

  FNewMsgReaderList.Free;

  FReadedMsgReaderList.Free;

end;

 

function TMsg.GetAllMsgCount: Integer;

begin

  Result := fAllMsgCount; //;NewMsgCount + ReadedMsgCount;

end;

 

 

function TMsg.GetMsgCode(MsgID: integer): integer;

begin

  Result := -1;

  if fcdsNewMsg.Locate('id',MsgID,[]) then

    Result := fcdsNewMsg.fieldByName('Msg_Code').AsInteger

  else if fcdsReadedMsg.Locate('id',MsgID,[]) then

    Result := fcdsReadedMsg.fieldByName('Msg_Code').AsInteger;

end;

 

 

function TMsg.GetvNewMsgData: OleVariant;

begin

  Result := fcdsNewMsg.Data;

end;

 

function TMsg.GetvReadedMsgData: OleVariant;

begin

  Result := fcdsReadedMsg.Data;

end;

 

procedure TMsg.NotifyChange(ReaderList: TObjectList; Value: integer);

var

  i: integer;

begin

  for i := 0 to ReaderList.Count -1 do

  begin

    if assigned(ReaderList[i]) then

      (ReaderList[i] as TCustomLabel).Caption := IntToStr(Value);

  end;

end;

 

procedure TMsg.RegisterNewMsg(Reader: TCustomLabel);

begin

  Reader.Caption := IntToStr(FNewMsgCount);

  FNewMsgReaderList.Add(Reader);

end;

 

procedure TMsg.RegisterReadedMsg(Reader: TCustomLabel);

begin

  Reader.Caption := IntToStr(FReadedMsgCount);

  FReadedMsgReaderList.Add(Reader);

end;

 

procedure TMsg.SetMsgReaded(MsgID: integer);

var

  i: integer;

begin

  if not fEduMstObj.ProxyObj.ReadAMsg(MsgID) then

    raise Exception.Create('设置消息已读属性失败!');

  if fcdsNewMsg.Locate('id',msgid,[]) then

  begin

    //将新消息里的记录插入到已读消息记录里

    fcdsReadedMsg.Insert;

    for i := 0 to fcdsNewMsg.FieldCount - 1 do

      fcdsReadedMsg.Fields[i].Value := fcdsNewMsg.Fields[i].Value;

    fcdsReadedMsg.Post;

    fcdsNewMsg.Delete;  //删除新生表里的记录

    fNewMsgCount := fcdsNewMsg.RecordCount;

    NotifyChange(FNewMsgReaderList,fNewMsgCount);

    fReadedMsgCount := fcdsReadedMsg.RecordCount;

    NotifyChange(FReadedMsgReaderList,fReadedMsgCount);

  end;

end;

 

procedure TMsg.SetNewMsgCount(Value: Integer);

begin

 

end;

 

 

 

procedure TMsg.UnregisterNewMsg(Reader: TCustomLabel);

var

  idx: integer;

begin

  idx := FNewMsgReaderList.IndexOf(Reader);

  if idx>=0 then

    FNewMsgReaderList.Delete(idx);

 

end;

 

end.

原创粉丝点击