When should I use composite design pattern?
Quoting from Design Patterns,
Use the Composite pattern when
- you want to represent part-whole hierarchies of objects.
- you want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.
A common usage is the one used as a motivating example in the book, a display system of graphic windows which can contain other windows and graphic elements such as images, text. The composite can be composed at run-time, and the client code can manipulate all the elements without concern for which type it is for common operations such as drawing.
A Composite is a pattern that is useful anytime you may need to selectively treat a group of objects that are part of a hierarchy as "the same" when they are in fact different. Typically the examples used talk in terms of treating leaves and nodes the same, but the pattern can also be extended to heterogeneous lists.
For example, consider a doctor visit. When you go to a doctor various things happen, you usually see a nurse or an assistant first, they take your temperature, etc. Then the doctor performs an exam and makes diagnoses. Then the doctor may do some treatment, but often the nurse comes back to finish up. And different activities are performed during the visit. You have observations like weight and temperature. But a lab for example will be a different object because it often requires a sample which may then be sent out and require results to be recorded at a later date.
So we have software that allows recording all this and it will usually create some kind of hierarchy with nodes like:
Encounter:
PreExam
Exam
Treatment
and under each of these nodes you will have a variety of entries such as diagnosis, observation, lab procedure, diagnostic, injection, etc.
This is all well and good, and you end up with a structured, albeit very complex hierarchical record of the encounter.
Now suppose you need to generate billing. Suddenly you are faced with a very different requirement. Your medical record was required to create a very accurate picture of the encounter. In billing though you do not care who did what or in what order, in fact you really don't care what an activity is beyond a billing code. You simply want a single list of billable activities, i.e codes.
Not only is this information embedded in a record, that record is also very hard to traverse because it contains a large number of different objects. It is also variable in hierarchical structure - if you have a nail in your head they may skip any kind of pre-exam, or exam for that matter and go to treatment. If you go in to have stitches removed there may not be any pre exam or exam. A yearly physical has no treatment. etc etc. Very difficult to enumerate this sort of object graph.
A Composite pattern solves all this. You define a common interface or base class for all the objects. Let's call it "CareEntry". CareEntry has a property BillingCode. Now your Encounter can appear to be a simple container with nothing but CareEntry objects inside. Your billing service can now simply enumerate everything inside without having to worry about whether something is a node (PreExam, Exam) versus a leaf(weight temperature), or what node the object is in (PreExam Exam, etc) or what the actual type of the object is (lab, injection etc). Everything is also a CareEntry and treated uniformly - You simply enumerate all CareEntry objects in an Encounter and collect each one that has an non-null billing code and you are done. It is as simple as that.