您的位置:首页 > 运维架构

《GOF设计模式》—代理(PROXY)—Delphi源码示例:更新前拷贝机制(copy-on-write)

2010-12-18 14:34 609 查看
示例:更新前拷贝机制(copy-on-write)
说明:
Proxy模式还可以对用户隐藏另一种称之为copy-on-write的优化方式,该优化与根据需要创建对象有关。拷贝一个庞大而复杂的对象是一种开销很大的操作,如果这个拷贝根本没有被修改,那么这些开销就没有必要。用代理延迟这一拷贝过程,我们可以保证只有当这个对象被修改的时候才对它进行拷贝。
在实现Copy-on-write时必须对实体进行引用计数,“拷贝代理”仅会增加引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正的拷贝它。在这种情况下,代理还必须减少实体的引用计数。当引用的数目为零时,这个实体将被删除。
Copy-on-Write可以大幅度的降低拷贝庞大实体时的开销。

代码:
unit uCopyOnWrite;

interface

uses
SysUtils,Dialogs;

type
TSubject = class
protected
procedure SetState(const Value: string); virtual; abstract;
public
procedure Request; virtual; abstract;
//---
property State: string write SetState;
end;
TRealSubject = class(TSubject)
private
FRefCount: Integer;
FState: string;
protected
procedure SetState(const Value: string); override;
public
constructor Create;
//---
procedure AddRef;
procedure Release;
function Copy: TRealSubject;
procedure Request; override;
//---
property RefCount: Integer read FRefCount;
end;
TProxy = class(TSubject)
private
FSubject: TRealSubject;
protected
procedure SetState(const Value: string); override;
public
constructor Create;
destructor Destroy; override;
//---
procedure Request; override;
//---
procedure Equal(Value: TRealSubject);
end;

implementation

constructor TRealSubject.Create;
begin
FRefCount := 0;
end;

procedure TRealSubject.AddRef;
begin
inc(FRefCount);
end;

procedure TRealSubject.Release;
begin
dec(FRefCount);
end;

procedure TRealSubject.Request;
begin
ShowMessage(FState);
end;

procedure TRealSubject.SetState(const Value: string);
begin
FState := Value;
end;

function TRealSubject.Copy: TRealSubject;
begin
Result := TRealSubject.Create;
Result.State := FState;
end;

constructor TProxy.Create;
begin
FSubject := nil;
end;

destructor TProxy.Destroy;
begin
self.Equal(nil);
//---
inherited;
end;

procedure TProxy.Request;
begin
if Assigned(FSubject) then
FSubject.Request;
end;

procedure TProxy.Equal(Value: TRealSubject);
//---
procedure _Clear;
begin
if Assigned(FSubject) then
begin
FSubject.Release;
if FSubject.RefCount = 0 then
FreeAndNil(FSubject);
end;
end;
//---
procedure _Equal;
begin
FSubject := Value;
if Assigned(FSubject) then
FSubject.AddRef;
end;
begin
if FSubject <> Value then
begin
_Clear;
_Equal;
end;
end;

procedure TProxy.SetState(const Value: string);
//---
procedure _Copy;
begin
if Assigned(FSubject) then
self.Equal(FSubject.Copy)
else
self.Equal(TRealSubject.Create);
end;
//---
procedure _Write;
begin
FSubject.State := Value;
end;
begin
_Copy;
_Write;
end;

end.

procedure TForm1.Button1Click(Sender: TObject);
var
ASubject1: TRealSubject;
ASubject2: TProxy;
begin
ASubject1 := TRealSubject.Create;
ASubject1.State := '123';
//---
ASubject2 := TProxy.Create;
try
ASubject2.Equal(ASubject1);
ASubject2.Request;
//---
ASubject2.State := 'abc';
ASubject2.Request;
finally
ASubject2.Free;
end;
end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐