《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
来源:互联网 发布:四库全书数据库 编辑:程序博客网 时间:2024/05/17 02:01
http://blog.csdn.net/starsky2006/article/details/6221441
示例:图形用户界面工具箱
说明:
许多图形用户界面工具箱将用户应用的界面表示与底下的应用数据分离。定义应用数据的类和负责界面表示的类可以各自独立地复用。当然它们也可一起工作。一个表格对象和一个柱状图对象可使用不同的表示形式描述同一个应用数据对象的信息。表格对象和柱状图对象互相并不知道对方的存在,这样使你可以根据需要单独复用表格或柱状图。但在这里是它们表现的似乎互相知道。当用户改变表格中的信息时,柱状图能立即反映这一变化,反过来也是如此。
这一行为意味着表格对象和棒状图对象都依赖于数据对象,因此数据对象的任何状态改变都应立即通知它们。同时也没有理由将依赖于该数据对象的对象的数目限定为两个,对相同的数据可以有任意数目的不同用户界面。
Observer模式描述了如何建立这种关系。
界面:
object Form3: TForm3
Left = 192
Top = 110
Width = 371
Height = 294
Caption = 'Form3'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 56
Top = 224
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 152
Top = 224
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 1
OnClick = Button2Click
end
end
代码:
unit uView;
interface
uses
Windows, SysUtils, Classes, Graphics, Controls,
Math;
type
TDataModel = class;
TView = class(TGraphicControl)
public
procedure Update1; virtual; abstract;
end;
TDataView = class(TView)
private
FModel: TDataModel;
public
constructor Create(AOwner: TComponent; AModel: TDataModel); reintroduce;
destructor Destroy; override;
//---
procedure Update1; override;
end;
TTableView = class(TDataView)
protected
procedure Paint; override;
end;
TStickView = class(TDataView)
protected
procedure Paint; override;
end;
TPieView = class(TDataView)
protected
procedure Paint; override;
end;
TModel = class
private
FObservers: TList;
public
constructor Create;
destructor Destroy; override;
//---
procedure Attach(AObserver: TView);
procedure Detach(AObserver: TView);
procedure Notify();
end;
RData = record
x, y, z: Integer;
end;
TDataModel = class(TModel)
private
FA: RData;
FB: RData;
FC: RData;
public
property A: RData read FA write FA;
property B: RData read FB write FB;
property C: RData read FC write FC;
end;
function GetData(AX, AY, AZ: Integer): RData;
implementation
function GetData(AX, AY, AZ: Integer): RData;
begin
with Result do
begin
x := AX;
y := AY;
z := AZ;
end;
end;
constructor TModel.Create;
begin
inherited;
//---
FObservers := TList.Create;
end;
destructor TModel.Destroy;
begin
FObservers.Free;
//---
inherited;
end;
procedure TModel.Attach(AObserver: TView);
begin
FObservers.Add(AObserver);
end;
procedure TModel.Detach(AObserver: TView);
begin
FObservers.Remove(AObserver);
end;
procedure TModel.Notify();
var
i: Integer;
begin
with FObservers do
begin
for i := 0 to Count - 1 do
TView(Items[i]).Update1;
end;
end;
procedure TTableView.Paint;
//---
procedure _ClearRect;
begin
with self.Canvas do
begin
with Brush do
begin
Color := clBlack;
Style := bsSolid;
end;
FillRect(self.ClientRect);
end;
end;
//---
procedure _DrawTable;
const
CNT_RowCount = 4;
CNT_ColCount = 4;
var
ARect: TRect;
ARowHeight, AColWidth: Integer;
//---
procedure _GetRect;
const
CNT_Size = 5;
begin
ARect := self.ClientRect;
with ARect do
begin
Left := Left + CNT_Size;
Right := Right - CNT_Size;
Top := Top + CNT_Size;
Bottom := Bottom - CNT_Size;
end;
end;
//---
procedure _GetAxis;
begin
with ARect do
begin
AColWidth := (Right - Left) div CNT_ColCount;
ARowHeight := (Bottom - Top) div CNT_RowCount;
end;
end;
//---
function _GetX(ACol: Integer): Integer;
begin
with ARect do
Result := Left + AColWidth * ACol;
end;
//---
function _GetY(ARow: Integer): Integer;
begin
with ARect do
Result := Top + ARowHeight * ARow;
end;
//---
procedure _DrawGrid;
var
i, X, Y: Integer;
begin
with self.Canvas do
begin
with Pen do
begin
Color := clYellow;
Width := 1;
Style := psSolid;
end;
Rectangle(ARect);
//---
with ARect do
begin
for i := 1 to CNT_RowCount - 1 do
begin
Y := _GetY(i);
MoveTo(Left, Y);
LineTo(Right, Y);
end;
//---
for i := 1 to CNT_ColCount - 1 do
begin
X := _GetX(i);
MoveTo(X, Top);
LineTo(X, Bottom);
end;
end;
end;
end;
//---
procedure _DrawData;
//---
procedure _DrawColDatas(ACol: Integer; const ADatas: array of string);
var
X, ARow: Integer;
begin
X := _GetX(ACol);
with self.Canvas do
begin
for ARow := Low(ADatas) to High(ADatas) do
TextOut(X + 2, _GetY(ARow) + 2, ADatas[ARow]);
end;
end;
begin
with self.Canvas do
begin
with Font do
begin
Color := clYellow;
Size := 10;
end;
end;
//---
with FModel do
begin
_DrawColDatas(0, ['', 'x', 'y', 'z']);
with A do
_DrawColDatas(1, ['a', IntToStr(x), IntToStr(y), IntToStr(z)]);
with B do
_DrawColDatas(2, ['b', IntToStr(x), IntToStr(y), IntToStr(z)]);
with C do
_DrawColDatas(3, ['c', IntToStr(x), IntToStr(y), IntToStr(z)]);
end;
end;
begin
_GetRect;
_GetAxis;
_DrawGrid;
_DrawData;
end;
begin
_ClearRect;
_DrawTable;
end;
constructor TDataView.Create(AOwner: TComponent; AModel: TDataModel);
begin
inherited Create(AOwner);
//---
FModel := AModel;
FModel.Attach(self);
end;
destructor TDataView.Destroy;
begin
FModel.Detach(self);
//---
inherited;
end;
procedure TDataView.Update1;
begin
self.Paint;
end;
procedure TStickView.Paint;
//---
procedure _ClearRect;
begin
with self.Canvas do
begin
with Brush do
begin
Color := clBlack;
Style := bsSolid;
end;
FillRect(self.ClientRect);
end;
end;
//---
procedure _DrawView;
const
CNT_ColCount = 3;
var
ARect: TRect;
AValueHeight, AColWidth: Integer;
//---
procedure _GetRect;
const
CNT_Size = 5;
begin
ARect := self.ClientRect;
with ARect do
begin
Left := Left + CNT_Size;
Right := Right - CNT_Size;
Top := Top + CNT_Size;
Bottom := Bottom - CNT_Size * 4;
end;
end;
//---
procedure _GetAxis;
var
AMaxValue: Integer;
begin
with ARect do
begin
AColWidth := (Right - Left) div CNT_ColCount;
//---
with FModel do
begin
AMaxValue := A.y;
with B do
if AMaxValue < y then
AMaxValue := y;
with C do
if AMaxValue < y then
AMaxValue := y;
AMaxValue := Trunc(AMaxValue * 1.2);
end;
//---
if AMaxValue > 0 then
AValueHeight := (Bottom - Top) div AMaxValue
else
AValueHeight := (Bottom - Top);
end;
end;
//---
function _GetX(ACol: Integer): Integer;
begin
with ARect do
Result := Left + trunc(AColWidth * (ACol + 0.5));
end;
//---
function _GetY(AValue: Integer): Integer;
begin
with ARect do
Result := Bottom - AValueHeight * AValue;
end;
//---
procedure _DrawAxis;
begin
with self.Canvas do
begin
with Pen do
begin
Color := clYellow;
Width := 1;
Style := psSolid;
end;
//---
with ARect do
begin
MoveTo(Left, Bottom);
LineTo(Right, Bottom);
//---
MoveTo(Left, Top);
LineTo(Left, Bottom);
end;
end;
end;
//---
procedure _DrawData;
//---
procedure _DrawColData(ACol: Integer; const ALable: string; const AValue: Integer);
var
X, AWidth: Integer;
begin
X := _GetX(ACol);
with self.Canvas do
begin
Brush.Style := bsClear;
TextOut(X, ARect.Bottom + 2, ALable);
//---
if AValue > 0 then
begin
with Brush do
begin
Color := clYellow;
Style := bsSolid;
end;
//---
AWidth := AColWidth div 4;
Rectangle(X - AWidth, _GetY(AValue), X + AWidth, ARect.Bottom);
end;
end;
end;
begin
with self.Canvas do
begin
with Font do
begin
Color := clYellow;
Size := 10;
end;
end;
//---
with FModel do
begin
_DrawColData(0, 'a', A.y);
_DrawColData(1, 'b', B.y);
_DrawColData(2, 'c', C.y);
end;
end;
begin
_GetRect;
_GetAxis;
_DrawAxis;
_DrawData;
end;
begin
_ClearRect;
_DrawView;
end;
procedure TPieView.Paint;
//---
procedure _ClearRect;
begin
with self.Canvas do
begin
with Brush do
begin
Color := clBlack;
Style := bsSolid;
end;
FillRect(self.ClientRect);
end;
end;
//---
procedure _DrawView;
var
ARect: TRect;
R, SumValue: Integer;
P: TPoint;
//---
procedure _GetRect;
const
CNT_Size = 5;
begin
ARect := self.ClientRect;
with ARect do
begin
Left := Left + CNT_Size;
Right := Right - CNT_Size;
Top := Top + CNT_Size;
Bottom := Bottom - CNT_Size;
end;
end;
//---
procedure _GetAxis;
begin
with ARect do
begin
R := Min(Right - Left, Bottom - Top) div 2;
P.X := (Left + Right) div 2;
P.Y := (Top + Bottom) div 2;
end;
//---
with FModel do
SumValue := A.y + B.y + C.y;
end;
//---
function _GetRadian(AValue: Integer): double;
begin
Result := 2 * Pi * (AValue / SumValue);
end;
//---
function _GetX(AValue, ARadius: Integer): Integer;
begin
Result := P.X + trunc(ARadius * cos(_GetRadian(AValue)));
end;
//---
function _GetY(AValue, ARadius: Integer): Integer;
begin
Result := P.Y - trunc(ARadius * sin(_GetRadian(AValue)));
end;
//---
procedure _DrawAxis(const AValues: array of Integer);
var
X, Y, AValue, i: Integer;
begin
with self.Canvas do
begin
with Pen do
begin
Color := clYellow;
Width := 1;
Style := psSolid;
end;
//---
Ellipse(P.X - R, P.Y - R, P.X + R, P.Y + R);
//---
MoveTo(P.X, P.Y);
LineTo(P.X + R, P.Y);
//---
AValue := 0;
for i := Low(AValues) to High(AValues) do
begin
AValue := AValue + AValues[i];
//---
X := _GetX(AValue, R);
Y := _GetY(AValue, R);
//---
MoveTo(P.X, P.Y);
LineTo(X, Y);
end;
end;
end;
//---
procedure _DrawData(const AValues: array of Integer; const ALables: array of string);
var
X, Y, AValue, ASumValue, ARadius, i: Integer;
begin
with self.Canvas do
begin
with Font do
begin
Color := clYellow;
Size := 10;
end;
Brush.Style := bsClear;
//---
ARadius := R div 2;
ASumValue := 0;
for i := Low(AValues) to High(AValues) do
begin
AValue := ASumValue + AValues[i] div 2;
ASumValue := ASumValue + AValues[i];
//---
X := _GetX(AValue, ARadius);
Y := _GetY(AValue, ARadius);
//---
with TextExtent(ALables[i]) do
TextOut(X - cX div 2, Y - cY div 2, ALables[i]);
end;
end;
end;
begin
_GetRect;
_GetAxis;
with FModel do
begin
if SumValue > 0 then
begin
_DrawAxis([A.y, B.y]);
_DrawData([A.y, B.y, C.y], ['a', 'b', 'c']);
end;
end;
end;
begin
_ClearRect;
_DrawView;
end;
end.
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, uView;
type
TForm3 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FModel: TDataModel;
FTableView: TTableView;
FStickView: TStickView;
FPieView:TPieView;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
FModel := TDataModel.Create;
//---
FTableView := TTableView.Create(nil, FModel);
with FTableView do
begin
Parent := self;
Top := 10;
Left := 10;
Width := 100;
Height := 100;
end;
//---
FStickView := TStickView.Create(nil, FModel);
with FStickView do
begin
Parent := self;
Top := 10;
Left := 120;
Width := 100;
Height := 100;
end;
//---
FPieView := TPieView.Create(nil, FModel);
with FPieView do
begin
Parent := self;
Top := 10;
Left := 230;
Width := 100;
Height := 100;
end;
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
FTableView.Free;
FStickView.Free;
FPieView.Free;
FModel.Free;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
with FModel do
begin
A := GetData(60, 50, 80);
B := GetData(30, 30, 10);
C := GetData(10, 20, 10);
//---
Notify;
end;
end;
procedure TForm3.Button2Click(Sender: TObject);
begin
with FModel do
begin
A := GetData(60, 20, 80);
B := GetData(30, 40, 10);
C := GetData(10, 40, 10);
//---
Notify;
end;
end;
end.
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:观察者接口
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:推模型(push model)
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:拉模型(pull model)
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:封装复杂的更新语义
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:时钟
- 《GOF设计模式》—装饰(DECORATOR)—Delphi源码示例:图形用户界面组件
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:显式地指定感兴趣的改变
- 《GOF设计模式》—桥接(BRIDGE)—Delphi源码示例:可移植的用户界面
- 《GOF设计模式》—桥接(BRIDGE)—Delphi源码示例:可移植的用户界面
- 《GOF设计模式》—备忘录(MEMENTO)—Delphi源码示例:图形编辑器
- 《GOF设计模式》—抽象工厂(Abstract Factory)—Delphi源码示例:用户界面工具包
- 《GOF设计模式》—中介者 (MEDIATOR)—Delphi源码示例:Colleague—Mediator通信(使用观察者模式)
- 《GOF设计模式》—代理(PROXY)—Delphi源码示例:远程代理(Remote Proxy)
- 《GOF设计模式》—代理(PROXY)—Delphi源码示例:保护代理(Protection Proxy)
- 《GOF设计模式》—代理(PROXY)—Delphi源码示例:智能指引(Smart Reference)
- 《GOF设计模式》—适配器(ADAPTER)—Delphi源码示例:适配器接口
- 原生JS获取CSS属性值
- 一个计算机爱好者的不完整回忆(五十二)终极之作4
- placement new
- 【专题】数位DP(按位DP)
- Web 开发人员需知的 Web 缓存知识
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
- 心理学分析
- 大话数据结构之二:算法
- “开源”是什么,能吃吗?
- a different object with the same identifier value was already associated with the session。
- 笔记:Vmware安装提示The MSI failed
- File各种类操作文件、文件夹
- Passing …(rest) parameters between functions
- JQuery实现iframe自适应高度