...das 'Choice Pattern' implementieren ?

Autor: Max Kleiner
Homepage: http://max.kleiner.com

Kategorie: VCL

{
The Choice Pattern needs one interface, n-classes which supports the interface and a
worker-class to provide the choice of an algorithm at runtime. The Choice Pattern is like the
Strategy Pattern, but smaller and more runtime in his behaviour.
With interfaces we don't have to concern about memory management.
Interface references are managed through reference-counting, which depends on the _AddRef
and _Release methods inherited from IUnknown. When an object is referenced only through
interfaces, there is no need to destroy it manually; the object is automatically destroyed when
the last reference to it goes out of scope.

The following restrictions apply.
- The member List can include only methods and properties.
- Fields are not allowed in interfaces.
- Interfaces have no constructors or destructors. They cannot be instantiated, except through

classes that implement their methods.
- Methods cannot be declared as virtual, dynamic, abstract, or override. Since interfaces do not

implement their own methods, these bindings have no meaning. So let's practice the
Choice Pattern in 5 steps:

}

//1.  We need an Interface in order to be type-compatible.

  
IChoicePattern = interface
   procedure 
doPatternSearch;
  end;

{
  2. We declare 2 or n classes. A class from an Interface can support/implement multiple
  interfaces. TInterfacedObject implements the methods of IUnknown, so TInterfacedObject
  automatically handles reference counting and memory management of interfaced objects.
  One of the concepts behind the design of interfaces is ensuring the lifetime management of the
  objects that implement them. The AddRef and Release methods of IUnknown provide a way of
  implementing this functionality.
}

  
TCheckFormatA = class(TInterfacedObject, IChoicePattern)
  public
    procedure 
doPatternSearch;
  end;

  TCheckFormatB = class(TInterfacedObject, IChoicePattern)
  public
    procedure 
doPatternSearch;
  end;


// 3. We need a worker-class which calls the runtime Interface-methods:

  
TDirWorker = class
    procedure 
CallCheck(myInst: IChoicePattern);
  end;


// 4. Now we implement the Interface Classes and the Worker Class too:

procedure TCheckFormatA.doPatternSearch;
var
  
ldbPath: string;
begin
  if 
FileExists(extractFileDir(Application.exeName) + '\' + DBNAME) then
    
ldbPath := extractFileDir(Application.exeName) + '\' + DBNAME;
  MessageDlg('formatASearch doing', mtInformation, [mbOK], 0);
end;


procedure TCheckFormatB.doPatternSearch;
var
  
ldbPath: string;
begin
  if 
OpenDialog1.Execute then
    
ldbPath := OpenDialog1.FileName;
  MessageDlg('formatBSearch doing', mtInformation, [mbOK], 0);
end;


procedure TDirWorker.CallCheck(myInst: IChoicePattern);
begin
  
myInst.doPatternSearch;
  MessageDlg('do_some_Work', mtInformation, [mbOK], 0);
end;


{
  Here we can see, no myInst.Free is needed. Each object from TCheckFormatA or
  TCheckFormatB is automatically destroyed. Interfaces track the lifetime of an object by
  incrementing the reference count on the object when an interface reference is passed, and will
  destroy the object when that reference count is zero.
}

// 5. at least the client calls the Choice Pattern and
// every object is local at runtime:

procedure TMainFrm.Button1Click(Sender: TObject);
begin
  with
(TDirWorker.Create) do
  begin
    
CallCheck(TCheckFormatA.Create);
    CallCheck(TCheckFormatB.Create);
    Free;
  end;
end;

// Have fun and choice with OP (Delphi, Kylix and FreePascal)

 

printed from
www.swissdelphicenter.ch
developers knowledge base