您的位置:首页 > 编程语言 > Delphi

设计模式学习笔记2:说说Mediator模式

2005-11-14 16:13 741 查看
GOF是这样说明它的意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
简而言之,就是将各对象间错综复杂的交互行为,变成多对一的交互。这很很容易让人想起现实生活中的中介服务单位(房产中介、劳务中介等)。
GOF书的第一章是很值得在学习模式前阅读的,里面对设计模式有总结,有比较,告诉你何时使用,如何使用等等。每个模式的“意图”(讲解模式的作用),“适用性”(讲解在什幺情况下使用模式),“效果”(缺点和优点)是应该关注的重点。没必要将它们全都记录下来,几次思考和运用下来就深有体会了!
我对这个模式的应用,写了个小例子,類似GOF书的中一个简单的GUI,如下图:



有一些交互行为:在文本输入框输入字符时,会在列表框中自动匹配相应的字符串。根据选择列表框中的内容,会确定单选按钮的状态。
没采用mediator的Delphi代码如下:
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    Edit1: TEdit;
    ListBox1: TListBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Button1: TButton;
    Button2: TButton;
    procedure Edit1Change(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
uses comm;
{$R *.dfm}
procedure TForm1.Edit1Change(Sender: TObject);
Var
  i: integer;
begin
  for i:=0 to ListBox1.Items.Count-1 do
    if pos(Edit1.Text,ListBox1.Items.Strings[i])<>0 then
    begin
      ListBox1.Selected[i]:=true;
      abort;
    end;
end;
procedure TForm1.ListBox1Click(Sender: TObject);
var
  i: integer;
begin
  for i:=0 to ListBox1.Items.Count-1 do
    if listbox1.Selected[i] then
    begin
      edit1.Text:= Listbox1.Items.Strings[i];
      RadioButton2.Enabled:= iif(pos('r',Listbox1.Items.Strings[i])<>0,true,false);
    end;
end;
end.
采用mediator的Delphi代码如下:
unit Unit2;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
type
  TMediator = class
    public
      procedure doEditChanged();
      procedure doListBoxChanged();
  end;
  TForm2 = class(TForm)
    Edit1: TEdit;
    ListBox1: TListBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Button1: TButton;
    Button2: TButton;
    procedure ListBox1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
    { Private declarations }
    mediator : TMediator;
  public
    { Public declarations }
  end;
var
  Form2: TForm2;
implementation
uses comm;
{$R *.dfm}
{ TForm2 }
procedure TForm2.FormCreate(Sender: TObject);
begin
  mediator:= TMediator.Create();
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
  FreeAndNil(mediator);
end;
procedure TForm2.Edit1Change(Sender: TObject);
begin
  mediator.doEditChanged;
end;
         
procedure TForm2.ListBox1Click(Sender: TObject);
begin
  mediator.doListBoxChanged;
end;
{ TMediator }
procedure TMediator.doEditChanged;
Var
  i: integer;
begin
  with form2 do
  begin
    for i:=0 to ListBox1.Items.Count-1 do
      if pos(Edit1.Text,ListBox1.Items.Strings[i])<>0 then
      begin
        ListBox1.Selected[i]:=true;
        abort;
      end;
  end;
end;
procedure TMediator.doListBoxChanged;
var
  i: integer;
begin
  with form2 do
  begin
    for i:=0 to ListBox1.Items.Count-1 do
      if listbox1.Selected[i] then
      begin
        edit1.Text:= Listbox1.Items.Strings[i];
        RadioButton2.Enabled:= iif(pos('r',Listbox1.Items.Strings[i])<>0,true,false);
      end;
  end;
end;
end.
你会发现这是一个很简单的例子,在原有的基础上加入了一个中介者mediator对象,将对象Edit1,ListBox1,RadioButton1, RadioButton2之间的交互全部封装了!一个对象与其它个对象的交互行为全交由它间接的执行。
这有什幺好处呢? 不错,form2及各对象更容易重用,Edit1等这些对象的行为变化,只需要生成mediator的子类即可。要是有众多对象的交互会让mediator变得很复杂,重用性会越来越小。这说明:Colleague对象(就是Edit1等)的重用是以牺牲mediator的重用为代价的!
作为系统学习的第二个模式是有原因的,因为它和facade模式有一些相似之处。这们都提供简化对象间交互的接口。但它们也是有区别的:Facade的协议是单向的,即Facade对象对子系统类提出请求,但反之则不行。相反,Mediator的协议是多向的。
刘艺在《Delphi模式编程》中举了个聊天室的例子,很不错!看懂一个模式是简单的,如何用好它要下点功夫。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息