Composite design pattern

1 / 26
About This Presentation
Title:

Composite design pattern

Description:

Composite design pattern Motivating example: Drawing A drawing consists of a number of basic drawing elements points, lines, circles, rectangles etc An example ... – PowerPoint PPT presentation

Number of Views:4
Avg rating:3.0/5.0

less

Transcript and Presenter's Notes

Title: Composite design pattern


1
Composite design pattern

2
Motivating example Drawing
  • A drawing consists of a number of basic drawing
    elements
  • points, lines, circles, rectangles etc

3
An example drawing
  • A drawing may for instance consist of a circle
    and four lines
  • The object diagram
  • The visual appearance

4
A more complicated drawing
  • We may want to draw more complicated things
  • The same group of a circle and four lines appears
    many times
  • we define that group to be a new drawing element,
    called StickMan
  • we can use StickMan as a new basic drawing element

5
Motivating example Drawing
  • A composite drawing element acts as a basic
    drawing element
  • the difference is that it contains other drawing
    element
  • the contained elements may be basic or composite

6
An example of a composite drawing
  • A drawing may consist of two stick men and a
    circle
  • The object diagram
  • The visual appearance

7
The Composite Design Pattern
  • Intent
  • Compose objects into tree structures to represent
    part-whole hierarchies. Composite lets clients
    treat individual objects and compositions of
    objects uniformly.

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
8
The Composite Design Pattern motivation
  • Motivation
  • Graphics applications like drawing editors and
    schematic capture systems let users build complex
    diagrams out of simple components. The user can
    group components to form larger components, which
    in turn can be grouped to form still larger
    components. A simple implementation could define
    classes for graphical primitives such as Text and
    Lines plus other classes that act as containers
    for these primitives.
  • But there's a problem with this approach Code
    that uses these classes must treat primitive and
    container objects differently, even if most of
    the time the user treats them identically. Having
    to distinguish these objects makes the
    application more complex. The Composite pattern
    describes how to use recursive composition so
    that clients don't have to make this distinction.

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
9
The Composite Design Pattern
From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
10
The Composite Design Pattern
  • The key to the Composite pattern is an abstract
    class that represents both primitives and their
    containers. For the graphics system, this class
    is Graphic. Graphic declares operations like Draw
    that are specific to graphical objects. It also
    declares operations that all composite objects
    share, such as operations for accessing and
    managing its children.
  • The subclasses Line, Rectangle, and Text (see
    preceding class diagram) define primitive
    graphical objects. These classes implement Draw
    to draw lines, rectangles, and text,
    respectively. Since primitive graphics have no
    child graphics, none of these subclasses
    implements child-related operations.
  • The Picture class defines an aggregate of Graphic
    objects. Picture implements Draw to call Draw on
    its children, and it implements child-related
    operations accordingly. Because the Picture
    interface conforms to the Graphic interface,
    Picture objects can compose other Pictures
    recursively.

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
11
Drawing in a graphical environment
  • The environment will call a graphical element to
    draw itself
  • the graphical element is typically a window or a
    frame
  • A graphics context is received as parameter to
    the draw function
  • a graphics context is typically an area on the
    screen
  • the window will ask its contents to draw itself
    on the graphics context
  • a text or a drawing
  • the leaves of the drawing ask the graphics
    context for the correct kind of drawing operation
  • drawLine, drawCircle etc
  • with the relevant parameters from the graphical
    element
  • the composite parts will ask all its components
    to draw themselves recursively

12
Class diagram for drawing in a graphical
environment
13
Drawing in various environments
  • Drawing can be done uniformly on different
    surfaces
  • By defining subclasses of the class
    GraphicsContext
  • Drawing on a text surface is easy
  • Implement for instance drawLine(Point p1, Point
    p2) as
  • cout ltlt (( ltlt p1.x ltlt , ltlt p1.y ltlt ),(
  • ltlt p2.x ltlt , ltlt p2.y ltlt )) ltlt endl
  • The figure elements will not notice any
    difference

14
Combination with handle-body
  • In combination with the handle-body pattern a
    part of a figure can change shape without losing
    its position in the figure

15
Handle-body object diagram stickman circle
16
Implementation in C Equipment
From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
17
Example code iterating
  • A default implementation of netPrice might use
    createIterator
  • factory method to return a default iterator on
    the equipment collection
  • to sum the net prices of the subequipment
  • Currency CompositeEquipmentnetPrice ()
  • Iterator i createIterator()
  • Currency total 0
  • for (i-gtfirst() !i-gtisDone() i-gtnext())
  • total i-gtcurrent()-gtnetPrice()
  • delete i
  • return total
  • Do not forget to delete the iterator after use

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
18
Example code a composite class
  • Now we can represent a computer chassis as a
    subclass of CompositeEquipment called Chassis.
    Chassis inherits the child-related operations
    from CompositeEquipment.
  • class Chassis public CompositeEquipment
  • public
  • Chassis(const char)
  • virtual Chassis()
  • virtual Watt Power()
  • virtual Currency NetPrice()
  • virtual Currency DiscountPrice()

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
19
Example code a simple application
  • We can define other equipment containers such as
    Cabinet and Bus in a similar way. That gives us
    everything we need to assemble equipment into a
    (pretty simple) personal computer
  • Cabinet cabinet new Cabinet("PC Cabinet")
  • Chassis chassis new Chassis("PC Chassis")
  • cabinet-gtAdd(chassis)
  • Bus bus new Bus("MCA Bus")
  • bus-gtAdd(new Card("16Mbs Token Ring"))
  • chassis-gtAdd(bus)
  • chassis-gtAdd(new FloppyDisk("3.5in Floppy"))
  • cout ltlt "The net price is " ltlt
    chassis-gtNetPrice()
  • ltlt endl

From Gamma et al Design Patterns, Elements of
Reusable Object-Oriented Software
20
Another composite example
  • A graphical windowing system

21
The composite dilemma
  • A composite super-class has two categories of
    subclasses
  • Container classes with member objects contained
    in them
  • End leave classes without member objects
  • How can component be uniformly accessed?
  • Leave classes do not have operations for
    accessing member objects
  • Gamma et al. present two basic approaches
  • make the operations dummy in the component base
    class
  • allows a uniform access to all component objects,
    whether or not containers
  • not implement the container operations
  • does not allow a uniform access to components
    since it requires the client to type check the
    component before call

22
Data abstraction and hierarchy
  • Barbara Liskov formulated a principle for
    subtyping.
  • This principle tells when inheritance can be used
    for subtyping.

23
Data abstraction and hierarchy
  • It is commonly called Liskovs substitution
    principle
  • It can be translated to contracts
  • the contracts for T express the behavior of o2
  • the contracts for T must be valid even for S if
    o1 shall be substituted for o2

24
Liskovs substitution principle quoted
  • 3.3. Type hierarchy
  • A type hierarchy is composed of subtypes and
    supertypes. The intuitive idea of a subtype is
    one whose objects provide all the behavior of
    objects of another type (the supertype) plus
    something extra.
  • What is wanted here is something like the
    following substitution property
  • If for each object o1 of type S there is an
    object o2 of type T such that for all programs P
    defined in terms of T, the behavior of P is
    unchanged when o1 is substituted for o2, then S
    is a subtype of T.

From Barbara Liskov, Data Abstraction and
Hierarchy, OOPSLA '87 Addendum to the
Proceedings, October 1987, pages 17-34.
25
Solution to the composite dilemma using contracts
  • Liskovs substitution principle dictates that
    both container and leave classes should be
    handled in a uniform way
  • they should obey the same contract
  • Introduce an operation in the component class to
    inquire if it is a container or not
  • this kind of operation is called a predicate
  • boolean isContainer()
  • Use this function in the precondition of the
    container specific functions
  • pre isContainer()
  • post the element is added to the container
  • void add(Component aComponent)

26
Consequences of the proposed solution
  • The responsibility is defined to be with the
    client
  • It may be implemented as a do nothing function
    in the Component base class
  • The Container subclass should override it to
    perform container operations
  • The container operations should only be called on
    container objects
  • Everything else is an error by client and the
    server (the component) is not bound by the
    postcondition of the contract
  • It is correct to do nothing in such a case
  • Every other imaginable implementation is also
    correct
Write a Comment
User Comments (0)