Mega Code Archive

 
Categories / Delphi / Examples
 

Simple example for the COMPOSITE Design Pattern

Title: Simple example for the COMPOSITE Design Pattern Question: What is the Composite Design Pattern ? How do you copy a directory with all subdirectories in a simple way ? Answer: The COMPOSITE Design Pattern lets clients treat individual objects and compositions of objects uniformly (according to Gamma, Helm, Johnson and Vlissides "Design Patterns", Addision-Wesley, 1995. Allthough this book now is nearly 8 years old, it is even in the new DOT NET World still important.) The idea is to define a Composite Class aComponentClass = class .. procedure DoSomething; virtual; end; aCompositeClass = class(aComponentClass) aList: tList; // List of "aComponentClass" Objects procedure DoSomething; override; ... end; Now you can call a single class method aComponentClass.DoSomething; in any case, whether the class is a composite class or not. The method "DoSomething" of the CompositeClass for example calls "DoSomething" for every item of the list. This allows you to ignore the difference between compositions of objects and individual objects. A simple example for a composition is a directory : a directory is a composition of files. A simple implementation of a class that copies a file or a complete directory with all subdirectories looks like this : uses Classes,SysUtils,..; tFile = class public fName : string; public constructor Create(Name : string); procedure Copy(DstDir : string); virtual; property Name : string read fName; end; tDirectory = class(tFile) private FileList : tList; public constructor Create(Name : string); destructor Destroy; procedure Copy(DstDir : string); override; property Name; end; { tFile } constructor tFile.Create(Name: string); begin fName:=Name; end; procedure tFile.Copy(DstDir: string); var SrcFilename,DstFilename : string; begin SrcFilename:=fName; DstFilename:=IncludeTrailingPathDelimiter(DstDir)+ ExtractFilename(fName); if FileExists(SrcFilename) then Windows.CopyFile(PChar(SrcFilename),PChar(DstFilename),false); end; { tDirectory } procedure tDirectory.Copy(DstDir: string); var i : integer; RelPath : string; begin if not DirectoryExists(DstDir) then ForceDirectories(DstDir); for i:=0 to FileList.Count-1 do if tFile(FileList[i]) is tDirectory then begin RelPath:=ExtractRelativePath(IncludeTrailingPathDelimiter(Name), tDirectory(FileList[i]).Name); tDirectory(FileList[i]).Copy(DstDir+'\'+RelPath) end else tFile(FileList[i]).Copy(DstDir) end; constructor tDirectory.Create(Name: string); var Root,s : string; sr : tSearchRec; begin inherited Create(Name); FileList := tList.Create; Root:=IncludeTrailingPathDelimiter(Name); s:=Root+'*.*'; if FindFirst(s, faAnyFile , sr) = 0 then begin repeat if (sr.Name = '.') or (sr.Name = '..') then continue; if ((sr.Attr and faDirectory) 0) then FileList.Add(tDirectory.Create(Root+sr.Name)) else FileList.Add(tFile.Create(Root+sr.Name)); until FindNext(sr) 0; FindClose(sr); end; end; destructor tDirectory.Destroy; var i : integer; begin for i:=0 to FileList.Count-1 do tFile(FileList[i]).Destroy; FileList.Free; end;