[ fromfile: children.xml id: children ]
According to [Gamma95], the Composite pattern is intended to facilitate building complex (composite) objects from simpler (component) parts by representing the part-whole hierarchies as tree-like structures. This must be done in such a way that clients do not need to distinguish between simple parts and more complex parts that are made up of (i.e., contain) simpler parts.
Figure 8.2 describes the Composite pattern. In this diagram, there are two distinct classes for describing two roles.
A composite object is something that can contain children.
A component object is something that can have a parent.
Many Qt classes use the Composite pattern: QObject, QWidget, QTreeWidgetItem, QDomNode, QHelpContentItem, QResource. The Composite pattern can be found in just about any tree-based structure.
In Figure 8.3, you can see that QObject is both composite and component.
You can express the whole-part relationship as a parent-child relationship between QObject
s.
The highest level (i.e., most "composite") QObject in such a tree (i.e., the root of the tree) will have children but no parent.
The simplest QObject
s (i.e., the leaf nodes of this tree) each have a parent but no children.
Client code can recursively deal with each node of the tree.
For an example of how the Composite pattern might be used, let's look at Suffolk University. In 1906 the founder, Gleason Archer, decided to start teaching the principles of law to a small group of tradesmen who wanted to become lawyers. He was assisted by one secretary and, after a while, a few instructors. The organizational chart for this new school was quite simple: a single office consisting of several employees with various tasks. As the enterprise grew, the chart gradually became more complex with the addition of new offices and departments. Today, more than a hundred years later, the Law School has been joined with a College of Arts and Sciences, a School of Management, a School of Art and Design, campuses abroad, and many specialized offices so that the organizational chart has become quite complex and promises to become more so. Figure 8.4 shows an abbreviated and simplified subchart of today's Suffolk University.
Each box in this chart is a component. It may be a composite and have subcomponents which, in turn, may be composite or simple components. For example, the PresidentOffice has individual employees (e.g., the President and his assistants) and suboffices (e.g., DiversityServices). Each leaf of this tree is an individual employee of the organization.
You can use the Composite pattern to model this structure.
Each node of the tree can be represented by an object of type OrgUnit
.
class OrgUnit : public QObject { public: QString getName(); double getSalary(); private: QString m_Name; double m_Salary; };
The QObject public interface enables you to build up a tree-like representation of the organization with code that instantiates an OrgUnit
and then calls setParent()
to add it to the appropriate child list.
For each OrgUnit
pointer ouptr
in the tree, initialize its m_Salary
data member as follows:
If ouptr
points to an individual employee, use that employee's actual salary.
Otherwise initialize it to 0.
You can implement the getSalary()
method like this:
double OrgUnit::getSalary() { QList<OrgUnit*> childlst = findChildren<OrgUnit*>(); double salaryTotal(m_Salary); if(!childlst.isEmpty()) foreach(OrgUnit* ouptr, childlst) salaryTotal += ouptr->getSalary(); return salaryTotal; }
A call to getSalary()
from any particular node returns the total salary for the part of the university represented by the subtree whose root is that node.
For example, if ouptr
points to University
, ouptr->getSalary()
returns the total salary for the entire university.
If ouptr
points to EnglishDpt
, then ouptr->getSalary()
returns the total salary for the English Department.
If ouptr
points to ProfE
, ouptr->getSalary()
simply returns ProfE
's individual salary.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |