Design patterns are set of best practices solutions to common problems. They are also an excellent dictionary which can enhance and speed up the communication between various team member. But they are also sometimes misused and lead to over-architected solutions.
By my opinion, every pattern usage in an application has to answer one simple questions:"What exact pain this pattern solves? "
If that question doesn't have a clear answer, I would challenge right there the decision for pattern usage
I already blogged about Dependency injection and service locator patterns and about Model View Presenter design pattern, but I'll be blogging again about them and about some other patterns with some "real world" problems scenarios which could clarify what kind of problems some pattern could solve. The intention of those examples are not to be "real" "real world examples" but to be still abstracted examples which could discover you use cases when you could use some pattern
So, stay tuned
Composite pattern - persistent control tree problem
To get a very detail explanation of what this pattern stands for check out the Armen's blog - Composite where he posted very detail article about pattern illustrated with one nice example
Problem - use case
The use case of the problem we would be solving in this example is next one:
We have a web page with fie different controls. The web page is organized in a web parts style, in the sense every control encapsulates the persistence logic inside of it.
When user clicks on a Save button of the page, page just commands to controls to persist the data without the knowledge what and how is been persisted.
The controls are named ControlA, ControlB, ControlC, ControlD and ControlE.
ControlB persistence requires that controlC and controlD would be persisted successfully first
ControlA persistence requires that ControlB and ControlE would be persisted successfully first
So, there's a tree structure
Why composite pattern?
Composite pattern in short is a pattern where some type has a member which is a collection of the same element.
So, if I would have an Interface IPersistable with a property of IPersistable collection type and bool Persist() method
If we would take a look at our problem we would see that this interface fits problem description: a bunch of controls which can be (or not) dependable on other controls. Our interface is: something which implements an IPersistable interface with a collection of something implementing the same interface.
Rule of thumb
Usage of composite pattern is usually appropriate whenever there are hierarchical tree structures where all the tree nods are of the same type.
Problem - solution example
Class Diagram of the solution
We would first implement the IPersistable interface on a BaseControl class which would also inherit from UserControl.
BaseControl would implement the IPersistable interface by defining the ICollection<IPersistable> field and expose it through the getter property named Dependencies.
BaseControl would implement the IPersistable method Persist() by defining it as virtual method which base implementation would just iterate through the Dependencies collection and call Persist() method on each collection member.
BaseControl code example:
Every web control would inherit from BaseControl and override its base implementation of the Perist() method.
Implementation would first call the base.Persist() which would caused the BaseControl to start iterating through the dependencies and persist them. If all the dependencies would persist successfully their state base.Perist() would return true value. Then the control itself could persist itself.
The same logic is implemented in all controls
ControlA implementation example
Now when we have defined composite behaviors of controls we have only to define the dependency structures of controls and form a composite tree. That would be done on a page level by simply setting the values of Dependencies property of every control.
(This is a setter type of dependency injection which I covered in Dependency injection and service locator patterns and I would be covering in separate article from "real world patterns" series of articles)
Page code example
Testing the solution
We would add a button on the page and inside of that button we would initiate persistence
protected void Button1_Click(object sender, EventArgs e)
And the result:
To download source code click here: Example source code