The intent of composite pattern is to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
- A part-whole hierarchy should be represented so that clients can treat part and whole objects uniformly.
- A part-whole hierarchy should be represented as tree structure.
- Define a unified
Componentinterface for both part (Leaf) objects and whole (Composite) objects. - Individual
Leafobjects implement theComponentinterface directly, andCompositeobjects forward requests to their child components.
- Component (IFileSystemComponent)
- declares an interface for objects in the composition.
- implements default behaviour for the interface common to all classes, as appropriate.
- Leaf (File)
- A leaf has no children.
- defines behavior for primitive objects in the composition.
- Composite (Folder)
- stores child components
- defines/implements behaviour for components having children.
- Client (FileSystem)
- manipulates objects in the composition through the Component interface.
- Clients use the Component class interface to interact with objects in the composite structure.
- If the recipient is a Leaf, then the request is handled directly.
- If the recipient is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding.
- Makes the client simple.
- It can apply the same operations over both composites and individual objects (leaves).
- In most cases we can ignore the differences between the composition of objects and leaves.
- Makes it easier to add new kinds of components
- Newly defined Composite or Leaf subclasses work automatically with existing structures and client code.
- In specific cases, it is difficult to restrict the components of the tree to only particular types. Therefore, to enforce such contraint, the program must rely on run-time checks, since it cannot use the type system of programming language.
Definition
Component
interfaceIFileSystemComponent{voidPrintName(stringprefix);}Leaf
classFile:IFileSystemComponent{publicstringName{get;set;}publicFile(stringname){this.Name=name;}publicvoidPrintName(stringprefix=""){Console.WriteLine("{0} {1}",prefix,Name);}}Composite
classFolder:IFileSystemComponent{privatereadonlyList<IFileSystemComponent>_fsComponents;publicstringName{get;set;}publicFolder(stringname){this.Name=name;this._fsComponents=newList<IFileSystemComponent>();}
...
public void PrintName(stringprefix=""){Console.WriteLine("{0} {1}",prefix,Name);foreach(varfileSystemComponentin_fsComponents){fileSystemComponent.PrintName(prefix+"\t");}}}Usage
FoldermainFolder=newFolder("Main Folder");FoldersubFolder1=newFolder("Sub Folder 1");FoldersubFolder2=newFolder("Sub Folder 2");mainFolder.Add(subFolder1);mainFolder.Add(subFolder2);mainFolder.Add(newFile("File 1 in Main Folder"));subFolder1.Add(newFile("File 1 in Sub Folder 1"));subFolder1.Add(newFile("File 2 in Sub Folder 1"));subFolder2.Add(newFile("File 1 in Sub Folder 2"));subFolder2.Add(newFolder("Empty folder in Sub Folder 2"));mainFolder.PrintName();Output
Main Folder
Sub Folder 1
File 1 in Sub Folder 1
File 2 in Sub Folder 1
Sub Folder 2
File 1 in Sub Folder 2
Empty folder in Sub Folder 2
File 1 in Main Folder- Chain of Responsibility - Often the component-parent link is used for a Chain of Responsibility.
- Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.
- Flyweight lets you share components, but they can no longer refer to their parents.
- Iterator can be used to traverse composites.
- Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes.

