Composite Pattern

Description:

» The Composite pattern arranges structured hierarchies so that single components and groups of components can be treated in the same way;
» The Composite pattern treats single objects and composite objects in the same way;
» The Composite pattern has to deal with two types: Components and Composites of those components; both types agree to conform to an interface of common operations;
» The Composite pattern has wide applicability and is often used in conjunction with the Decorator, Iterator, and Visitor patterns.

Use When:

» You have an irregular structure of objects and composites of the objects;
» You want clients to ignore all but the essential differences between individual objects and composites of objects;
» You want to treat all objects in a composite uniformly.

//Define the IComponent interface to be used as the "blueprint" for the composite and component classes.
public interface IComponent
{
bool Add(IComponent component);
bool Remove(IComponent component);
IComponent Find(string name);
string Display();
string Name { get; set; }
}

//The Album class (object) inherits from the IComponent interface and represents the composite component.
//This class contains a list of IComponent components.
public class Album : IComponent
{
public string Name { get; set; }
public List<IComponent> Photos { get; private set; }

public Album(string name)
{
Name = name;
Photos = new List<IComponent>();
}

public bool Add(IComponent component)
{
Photos.Add(component);
return (true);
}

public bool Remove(IComponent component)
{
IComponent componentFound = Find(component.Name);

if (componentFound != null)
{
Photos.Remove(componentFound);
return (true);
}

return (false);
}

public IComponent Find(string name)
{
return Photos.Find(delegate(IComponent component)
{
return (component.Name == name);
}
);
}

public string Display()
{
StringBuilder sb = new StringBuilder();
foreach (IComponent component in Photos)
{
sb.Append(string.Format("Photo: {0}\n", component.Name));
}

return (sb.ToString());
}
}

//The Photo class (object) inherits from the IComponent interface and represents a single component.
public class Photo : IComponent
{
public string Name { get; set; }

public Photo(string name)
{
Name = name;
}

public bool Add(IComponent component)
{
throw new Exception("Cannot add to a Photo.");
}

public bool Remove(IComponent component)
{
throw new Exception("Cannot remove Photo directly.");
}

public bool Find(string name)
{
throw new Exception("Cannot find a Photo.");
}

public string Display()
{
return (string.Format("The name of the photo is {0}.", Name));
}

public override string ToString()
{
return Name;
}
}
Image
//Define the IComponent interface to be used as the "blueprint" for the composite and component classes.
public interface IComponent
{
bool Add(IComponent component);
bool Remove(IComponent component);
IComponent Find(string name);
string Display();
string Name { get; set; }
}

//The Album class (object) inherits from the IComponent interface and represents the composite component.
//This class contains a list of IComponent components.
public class Album : IComponent
{
public string Name { get; set; }
public List<IComponent> Photos { get; private set; }

public Album(string name)
{
Name = name;
Photos = new List<IComponent>();
}

public bool Add(IComponent component)
{
Photos.Add(component);
return (true);
}

public bool Remove(IComponent component)
{
IComponent componentFound = Find(component.Name);

if (componentFound != null)
{
Photos.Remove(componentFound);
return (true);
}

return (false);
}

public IComponent Find(string name)
{
return Photos.Find(delegate(IComponent component)
{
return (component.Name == name);
}
);
}

public string Display()
{
StringBuilder sb = new StringBuilder();
foreach (IComponent component in Photos)
{
sb.Append(string.Format("Photo: {0}\n", component.Name));
}

return (sb.ToString());
}
}

//The Photo class (object) inherits from the IComponent interface and represents a single component.
public class Photo : IComponent
{
public string Name { get; set; }

public Photo(string name)
{
Name = name;
}

public bool Add(IComponent component)
{
throw new Exception("Cannot add to a Photo.");
}

public bool Remove(IComponent component)
{
throw new Exception("Cannot remove Photo directly.");
}

public bool Find(string name)
{
throw new Exception("Cannot find a Photo.");
}

public string Display()
{
return (string.Format("The name of the photo is {0}.", Name));
}

public override string ToString()
{
return Name;
}
}