Delphi - шаблон проектирования прокси - проблема интерфейса

Привет Я пытаюсь создавать шаблоны проектирования в Delphi, и, поскольку мне не удалось найти справочный материал, который мне нравится в Delphi, я конвертирую шаблоны, которые у меня есть в книге O'Reilly C # 3.0 Design Patterns. Но проблема не в этом. Я создал шаблон Proxy из этой книги, но есть некоторые концепции интерфейсов Delphi, конструкторов, деструктора и общего времени жизни и поведения объекта, которые я, по-видимому, не понимаю. Сначала я опубликую свой код:

unit Unit2;  

interface  

uses
  SysUtils;

type
  ISubject = interface
  ['{78E26A3C-A657-4327-93CB-F3EB175AF85A}']
  function Request(): string;
end;

  TSubject = class
  public
    function Request(): string;
    constructor Create();
  end;

  TProxy = class (TInterfacedObject, ISubject)
  private
    FSubject: TSubject;
  public
    function Request(): String;
    destructor Destroy(); override;
  end;

  TProtectionProxy = class (TInterfacedObject, ISubject)
  private
    FSubject: TSubject;
    FPassword: String;
  public
    constructor Create();
    destructor Destroy(); override;
    function Authenticate(supplied: String): String;
    function Request(): String;
  end;

implementation

{ TSubjectAccessor.TProxy }

destructor TProxy.Destroy;
begin
  if Assigned(Self.FSubject) then
    FreeAndNil(Self.FSubject);
  inherited;
end;

function TProxy.Request: String;
begin
  if not Assigned(Self.FSubject) then begin
    WriteLn('Subject Inactive');
    Self.FSubject := TSubject.Create();
  end;
  WriteLn('Subject active');
  Result := 'Proxy: Call to ' + Self.FSubject.Request();
end;

{ TSubject }

constructor TSubject.Create;
begin
  inherited;
end;

function TSubject.Request: string;
begin
  Result := 'Subject Request Choose left door' + #10;
end;

{ TProtectionProxy }

function TProtectionProxy.Authenticate(supplied: String): String;
begin
  if (supplied <> Self.FPassword) then begin
    Result := 'Protection proxy: No Access!';
  end else begin
    Self.FSubject := TSubject.Create();
    Result := 'Protection Proxy: Authenticated';
  end;
end;

constructor TProtectionProxy.Create;
begin
  Self.FPassword := 'Abracadabra';
end;

destructor TProtectionProxy.Destroy;
begin
  if Assigned(Self.FSubject) then
    FreeAndNil(Self.FSubject);
  inherited;
end;

function TProtectionProxy.Request: String;
begin
  if not Assigned(Self.FSubject) then begin
    Result := 'Protection Proxy: Authenticate first!';
  end else begin
    Result := 'Protection Proxy: Call to ' + Self.FSubject.Request();
  end;
end;

end.

Это интерфейсы и классы, используемые в шаблоне. Далее следует код, который использует эти типы:

program Structural.Proxy.Pattern;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit2 in 'Unit2.pas';

var
  subject: ISubject;

begin
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;

  try
    WriteLn('Proxy Pattern' +  #10);

    try
      subject := TProxy.Create();
      WriteLn(subject.Request());
      WriteLn(subject.Request());

      subject := TProtectionProxy.Create();
      WriteLn(subject.Request());
      WriteLn(TProtectionProxy(subject).Authenticate('Secret'));
      WriteLn(TProtectionProxy(subject).Authenticate('Abracadabra'));
      WriteLn(subject.Request());

      ReadLn;      
    finally

    end;

  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

Законно ли просто назначать новый экземпляр объекта переменной интерфейса? При отладке я вижу, что сначала выполняется конструктор TProtectionProxy, а затем деструктор TProxy. После создания TProtectionProxy Authenticate ('Abracadabra') должен быть проверен в логике, но в отладчике FPassword пуст, а он был назначен в конструкторе? Это очень загадочно. Но когда я закрываю приложение, в деструкторе пароль присутствует? TProtectionProxy (тема) в порядке, но я прочитал, что это не рекомендуется, но (объект как TProtectionProxy) по какой-то причине не компилировался (оператор не применим ...)? Я добавил деструкторы из-за поля FSubject. Это нормально? Можно ли инициировать переменную поля в той же строке, где она объявлена, или мне нужно инициировать ее в конструкторе, как в TProtectionProxy?

Я знаю, что это очень много, но я не знаю никого, кто знает Delphi ООП так хорошо, что я могу спросить.

Спасибо.


Это новая версия, которая мне подходит. Спасибо за вашу помощь.

unit Unit2;

interface

uses
  SysUtils;

type
  ISubject = interface
  ['{78E26A3C-A657-4327-93CB-F3EB175AF85A}']
    function Request(): string;
  end;

  IProtected = interface
  ['{928BA576-0D8D-47FE-9301-DA3D8F9639AF}']
    function Authenticate(supplied: string): String;
  end;

  TSubject = class
  public
    function Request(): string;
  end;

  TProxy = class (TInterfacedObject, ISubject)
  private
    FSubject: TSubject;
  public
    function Request(): String;
    destructor Destroy(); override;
  end;

  TProtectionProxy = class (TInterfacedObject, ISubject, IProtected)
  private
    FSubject: TSubject;
    const FPassword: String =  'Abracadabra';
  public
    destructor Destroy(); override;
    function Authenticate(supplied: String): String;
    function Request(): String;
  end;

implementation

{ TSubjectAccessor.TProxy }

destructor TProxy.Destroy;
begin
  if Assigned(FSubject) then
    FreeAndNil(FSubject);
  inherited;
end;

function TProxy.Request: String;
begin
  if not Assigned(FSubject) then begin
    WriteLn('Subject Inactive');
    FSubject := TSubject.Create();
  end;
  WriteLn('Subject active');
  Result := 'Proxy: Call to ' + FSubject.Request();
end;

{ TSubject }

function TSubject.Request: string;
begin
  Result := 'Subject Request Choose left door' + #10;
end;

{ TProtectionProxy }

function TProtectionProxy.Authenticate(supplied: String): String;
begin
  if (supplied <> FPassword) then begin
    Result := 'Protection proxy: No Access!';
  end else begin
    FSubject := TSubject.Create();
    Result := 'Protection Proxy: Authenticated';
  end;
end;

destructor TProtectionProxy.Destroy;
begin
  if Assigned(FSubject) then
    FreeAndNil(FSubject);
  inherited;
end;

function TProtectionProxy.Request: String;
begin
  if not Assigned(FSubject) then begin
    Result := 'Protection Proxy: Authenticate first!';
  end else begin
    Result := 'Protection Proxy: Call to ' + FSubject.Request();
  end;
end;

end.

и программный код:

program Structural.Proxy.Pattern;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit2 in 'Unit2.pas';

var
  subject: ISubject;
  protect: IProtected;

begin
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;

  try
    WriteLn('Proxy Pattern' +  #10);

    try
      subject := TProxy.Create();
      WriteLn(subject.Request());
      WriteLn(subject.Request());

      subject := nil;
      subject := TProtectionProxy.Create();
      WriteLn(subject.Request());
      if Supports(subject, IProtected, protect) then begin
        WriteLn(protect.Authenticate('Secret'));
        WriteLn(protect.Authenticate('Abracadabra'));
      end;
      WriteLn(subject.Request());
      ReadLn;      
    finally

    end;

  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

Я удалил все конструкторы, потому что теперь они действительно ничего не делают. А конструкторы без параметров по умолчанию унаследованы от TInrefacedObject, верно? Я оставил Self, я хотел бы услышать, почему его не следует использовать?

спасибо

У меня есть полная реализация шаблона на http://delphipatterns.blog.com/2011/02/ 22 / proxy-2 /

5
задан elector 22 March 2011 в 13:38
поделиться