1 Structural Patterns How classes and objects are composed to form larger structures Structural...

90
1 Structural Patterns How classes and objects are composed to form larger structures Structural class patterns: use inheritance to compose interfaces or implementations Structural object patterns: describe ways to compose objects to realize new functionality

Transcript of 1 Structural Patterns How classes and objects are composed to form larger structures Structural...

Page 1: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

1

Structural Patterns

How classes and objects are composed to form larger structures

Structural class patterns: use inheritance to compose interfaces or implementations

Structural object patterns: describe ways to compose objects to realize new functionality

Page 2: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

2

Structural Patterns

Adapter Façade Flyweight Bridge Composite Proxy

Page 3: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

US-made laptop in a European country

Page 4: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

4

Structural Patterns - Adapter Intent:

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces

Motivation: Sometimes a toolkit or class library can not be used because its

interface is incompatible with the interface required by an application

We can not change the library interface, since we may not have its source code

Even if we did have the source code, we probably should not change the library for each domain-specific application

Page 5: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Adapter Pattern

Client

+Request()

Target

+Request()

Adapter

+SpecificRequest()

Adaptee

adaptee.SpecificRequest()

The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces

Page 6: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

6

Structural Patterns - Adapter TextShape Example: a drawing editor that lets users

draw and arrange graphical elements (lines, polygons, text, etc.) into pictures and diagrams. The drawing editor's key abstraction is the graphical object, which has an editable shape and can draw itself. The interface for graphical objects is defined by an abstract class called Shape. The editor defines a subclass of Shape for each kind of graphical object: a LineShape class for lines, a PolygonShape class for polygons, a TextShape class for text editing. by inheriting Shape's interface and TextView's

implementation by composing a TextView instance within a TextShape

and implementing TextShape in terms of TextView's interface

Page 7: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

7

Structural Patterns - Adapter

Class Diagram: TextShape Example

Page 8: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

8

Structural Patterns - AdapterStructure: Class Diagram

A class adapter uses multiple inheritance to adapt one interface to another:

An object adapter relies on object composition:

Page 9: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

9

Structural Patterns - Adapter

Target — defines the domain-specific interface that the client uses. Client — collaborates with objects conforming to the Target interface. Adaptee — defines an existing interface that needs adapting. Adapter — adapts the interface of Adaptee to the Target interface.

Participants

Clients call operations on an Adapter instance. In turn, the Adapter calls Adaptee operations that carry out the request.

Collaborations

Page 10: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

10

Structural Patterns - Adapter

you want to use an existing class, and its interface does not match the one you need.

you want to create a reusable class that cooperates with unrelated or unforeseen classes that don't have compatible interfaces.

Applicability

Implementation Issues

How much adapting should be done? Simple interface conversion that just changes operation

names and order of arguments Totally different set of operations

Does the adapter provide two-way transparency? A two-way adapter supports both the Target and the

Adaptee interface. It allows an adapted object (Adapter) to appear as an Adaptee object or a Target object

Page 11: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

11

Structural Patterns - Adapter Adapter Pattern Example 1: The classic round pegs and square pegs! Here's the SquarePeg class:

/*** The SquarePeg class.* This is the Target class.*/public class SquarePeg {

public void insert(String str) {System.out.println("SquarePeg insert(): " + str);

}}

Page 12: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

12

Structural Patterns - Adapter And the RoundPeg class:

/*** The RoundPeg class.* This is the Adaptee class.*/public class RoundPeg {

public void insertIntoHole(String msg) {System.out.println("RoundPeg insertIntoHole(): " + msg);

}}

If a client only understands the SquarePeg interface for inserting pegs using the insert() method, how can it insert round pegs? A peg adapter!

Page 13: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

13

Structural Patterns - Adapter Here is the PegAdapter class:

/*** The PegAdapter class.* This is the Adapter class.* It adapts a RoundPeg to a SquarePeg.* Its interface is that of a SquarePeg.*/public class PegAdapter extends SquarePeg {

private RoundPeg roundPeg;

public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}

public void insert(String str) {roundPeg.insertIntoHole(str);}}

Page 14: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

14

Structural Patterns - Adapter Typical client program:

// Test program for Pegs.public class TestPegs {

public static void main(String args[]) {

// Create some pegs.RoundPeg roundPeg = new RoundPeg();SquarePeg squarePeg = new SquarePeg();

// Do an insert using the square peg.squarePeg.insert("Inserting square peg...");

// Now we'd like to do an insert using the round peg.// But this client only understands the insert()// method of pegs, not a insertIntoHole() method.// The solution: create an adapter that adapts// a square peg to a round peg!PegAdapter adapter = new PegAdapter(roundPeg);adapter.insert("Inserting round peg...");}

}

Page 15: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

15

Structural Patterns - Adapter Client program output:

SquarePeg insert(): Inserting square peg...RoundPeg insertIntoHole(): Inserting round peg...

Page 16: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

16

Structural Patterns - Adapter Adapter Pattern Example 2: Notice in Example 1 that the PegAdapter adapts a

RoundPeg to a SquarePeg. The interface for PegAdapter is that of a SquarePeg.

What if we want to have an adapter that acts as a SquarePeg or a RoundPeg? Such an adapter is called a two-way adapter. One way to implement two-way adapters is to use

multiple inheritance, but we can't do this in Java But we can have our adapter class implement two

different Java interfaces!

Page 17: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

17

Structural Patterns - Adapter Here are the interfaces for round and square pegs:

/***The IRoundPeg interface.*/public interface IRoundPeg {

public void insertIntoHole(String msg);}

/***The ISquarePeg interface.*/public interface ISquarePeg {

public void insert(String str);}

Page 18: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

18

Structural Patterns - Adapter Here are the new RoundPeg and SquarePeg classes. These

are essentially the same as before except they now implement the appropriate interface.

// The RoundPeg class.public class RoundPeg implements IRoundPeg {

public void insertIntoHole(String msg) {System.out.println("RoundPeg insertIntoHole(): " + msg);}

}// The SquarePeg class.public class SquarePeg implements ISquarePeg {

public void insert(String str) {System.out.println("SquarePeg insert(): " + str);}

}

Page 19: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

19

Structural Patterns - Adapter Here is the new PegAdapter class:

/*** The PegAdapter class.* This is the two-way adapter class.*/public class PegAdapter implements ISquarePeg, IRoundPeg {

private RoundPeg roundPeg;private SquarePeg squarePeg;

public PegAdapter(RoundPeg peg) {this.roundPeg = peg;}public PegAdapter(SquarePeg peg) {this.squarePeg = peg;}public void insert(String str) {roundPeg.insertIntoHole(str);}public void insertIntoHole(String msg){squarePeg.insert(msg);}

}

Page 20: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

20

Structural Patterns - Adapter A client that uses the two-way adapter:

// Test program for Pegs.

public class TestPegs {

public static void main(String args[]) {

// Create some pegs.

RoundPeg roundPeg = new RoundPeg();

SquarePeg squarePeg = new SquarePeg();

// Do an insert using the square peg.

squarePeg.insert("Inserting square peg...");

// Create a two-way adapter and do an insert with it.

ISquarePeg roundToSquare = new PegAdapter(roundPeg);

roundToSquare.insert("Inserting round peg...");

// Do an insert using the round peg.

roundPeg.insertIntoHole("Inserting round peg...");

// Create a two-way adapter and do an insert with it.

IRoundPeg squareToRound = new PegAdapter(squarePeg);

squareToRound.insertIntoHole("Inserting square peg...");

}

}

Page 21: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

21

Structural Patterns - Adapter Client program output:

SquarePeg insert(): Inserting square peg...RoundPeg insertIntoHole(): Inserting round peg...RoundPeg insertIntoHole(): Inserting round peg...SquarePeg insert(): Inserting square peg...

Page 22: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

22

Structural Patterns - Adapter Motivation Example 3: class Shape {public:

Shape();virtual void BoundingBox(Point& bottomLeft, Point& topRight) const;virtual Manipulator* CreateManipulator() const;};

class TextView {public:

TextView();void GetOrigin(Coord& x, Coord& y) const;void GetExtent(Coord& width, Coord& height) const;virtual bool IsEmpty() const;

};

Page 23: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

23

Structural Patterns - Adapter Multiple Inheritance:

Key to Class Adapter: use one inheritance branch to inherit the interface and another branch to inherit the implementation

class TextShape : public Shape, private TextView {public:

TextShape();

virtual void BoundingBox(Point& bottomLeft, Point& topRight

) const;virtual bool IsEmpty() const;virtual Manipulator* CreateManipulator() const;

};

Page 24: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

24

Structural Patterns - Adapter void TextShape::BoundingBox (Point& bottomLeft, Point& topRight) const {

Coord bottom, left, width, height;

GetOrigin(bottom, left);GetExtent(width, height);

bottomLeft = Point(bottom, left);topRight = Point(bottom + height, left + width);

}

bool TextShape::IsEmpty () const {return TextView::IsEmpty();

}

Manipulator* TextShape::CreateManipulator () const {return new TextManipulator(this);

}

Page 25: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

25

Structural Patterns - Adapter Object adapter: use object composition to

combine classes with different interfaces

class TextShape : public Shape {public:

TextShape(TextView*);virtual void BoundingBox(Point& bottomLeft, Point& topRight) const;virtual bool IsEmpty() const;virtual Manipulator* CreateManipulator() const;

private:TextView* _text;

};

Page 26: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

26

Structural Patterns - Adapter TextShape::TextShape (TextView* t) {_text = t;}

void TextShape::BoundingBox (Point& bottomLeft, Point& topRight) const {Coord bottom, left, width, height;

_text->GetOrigin(bottom, left);_text->GetExtent(width, height);bottomLeft = Point(bottom, left);topRight = Point(bottom + height, left + width);

}

bool TextShape::IsEmpty () const { return _text->IsEmpty();

}

Manipulator* TextShape::CreateManipulator () const { return new TextManipulator(this);

}

Page 27: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

27

Structural Patterns - Adapter Compared with the class adapter case, the object

adapter requires a little more effort to write, but it's more flexible.

the object adapter version of TextShape will work equally well with subclasses of TextView—the client simply passes an instance of a TextView subclass to the TextShape constructor

Page 28: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Real World Adapters

Old world Enumerators

<<interface>>Enumeration

hasMoreElements()nextElement

• New world Enumerators

<<interface>>Iterator

hasNext()next()remove()

Page 29: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Home Sweet Home Theater

A DVD player A projection video system An automated screen Surround sound And even

A popcorn popper

Page 30: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Home Theater

+on()+off()+setCd()+setDvd()+setStereoSound()+setSurroundSound()+setTuner()+setVolume()

-tuner-dvdPlayer-cdPlayer

Amplifier

+on()+off()+eject()+pause()+play()+stop()

-amplifierCdPlayer

+on()+off()+eject()+pause()+play()+stop()+setSurroundAudio()+setTwoChannelAudio()

-amplifierDvdPlayer

+on()+off()+tvMode()+wideScreenMode()

-dvdPlayerProjector

+on()+off()+setAm()+setFm()+setFrequency()

-amplifierTuner

+on()+off()+dim()

TheaterLights

+on()+off()+pop()

PopcornPopper

+up()+down()

Screen

Page 31: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Watching a movie

1. Turn on the popcorn popper2. Start the popper popping3. Dim the lights4. Put the screen down5. Turn the projector on6. Set the project input to DVD7. Put the projector on wide-screen mode8. Turn the sound amplifier on9. Set the amplifier to DVD input10. Set the amplifier to surround sound11. Set the amplifier volumn to medium12. Turn the DVD player on13. Start the DVD player playing

Page 32: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

What if: The movie is over?

Just want to listen to CD or Radio?

Upgrade your system?

Page 33: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

+on()+off()+setCd()+setDvd()+setStereoSound()+setSurroundSound()+setTuner()+setVolume()

-tuner-dvdPlayer-cdPlayer

Amplifier

+on()+off()+eject()+pause()+play()+stop()

-amplifierCdPlayer

+on()+off()+eject()+pause()+play()+stop()+setSurroundAudio()+setTwoChannelAudio()

-amplifierDvdPlayer

+on()+off()+tvMode()+wideScreenMode()

-dvdPlayerProjector

+on()+off()+setAm()+setFm()+setFrequency()

-amplifierTuner

+on()+off()+dim()

TheaterLights

+on()+off()+pop()

PopcornPopper

+up()+down()

Screen

+watchMovie()+endMovie()+listenToCd()+endCd()+listernToReadio()+endRadio()

HomeTheaterFacade watchMovie()

Page 34: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

34

Structural Patterns - Façade

Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.

Applicability Provides a simple interface to a complex subsystem. Decouples the details of a subsystem from clients and other

subsystems. Provides a layered approach to subsystems.

Intent

Page 35: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

35

Structural Patterns - Façade

Class Diagram

subsystem

Facade

Page 36: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

36

Structural Patterns - Façade

Motivation

Page 37: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

37

Structural Patterns - Façade

Façade Knows which classes are responsible for each request. Delegates client requests to appropriate objects.

Subsystem classes Implement subsystem functionality. Handle work assigned by the Façade object. Have no knowledge of the façade.

Participants

Clients communicate with the subsystem sending requests to the Façade. Reduces the number of classes the client deals with. Simplifies the subsystem.

Clients do not have to access subsystem objects directly.

Collaborations

Page 38: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

38

Structural Patterns - FaçadeConsequences

Benefits• It hides the implementation of the subsystem from clients, making the subsystem easier to use• It promotes weak coupling between the subsystem and its clients. This allows you to change the classes that comprise the subsystem without affecting the clients.• It reduces compilation dependencies in large software systems• It simplifies porting systems to other platforms, because it's less likely that building one subsystem requires building all others • It does not prevent sophisticated clients from accessing the underlying classes• Note that Facade does not add any functionality, it just simplifies interfacesLiabilities• It does not prevent clients from accessing the underlying classes!

Page 39: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

39

Structural Patterns - Façade

An example: Compiler

Page 40: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Facade Pattern

The Facade Pattern provides a unified interface to a set of interfaces in the subsystems. Façade defines a higher-level interface that makes the subsystem easier to use

Principle of Least Knowledge—talk only to your immediate friend.

Page 41: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Hints We should only invoke methods that

belong to: The object itself Objects passed in as a parameter to the

method Any object the method creates or instantiates Any components of the object

Page 42: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bullet Points

When you need to use an existing class and its interface is not the one you need, use an adapter

When you need to simplify and unify a large interface or complex set of interfaces, use a façade

An adapter changes an interface into one a client expects

Page 43: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bullet Points

A façade decouples a client from a complex subsystem.

Implementing an adapter may require little work or a great deal of work depending on the size and complexity of the target interface

Implementing a façade requires that we compose the façade with its subsystem and use delegation to perform the work of the façade

Page 44: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bullet Points

There are two forms of the Adapter Pattern: object and class adapters. Class adapters require multiple inheritance

You can implement more than one façade for a subsystem

An adapter wraps an object to change its interface and a façade “wraps” a set of object to simplify.

Page 45: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

What if there are too many instances?

Page 46: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Flyweight Pattern

+GetFlyweight(in key)

FlyweightFactory

+Operation(in extrinsicState)

Flyweight

+Operation(in extrinsicState)

-intrinsicState

UnsharedConcreteFlyweight

+Operation(in extrinsicState)

-allState

ConcreteFlyweightClient

if flyweights[key] exists return existing flyweightelse create new flyweight add to pool of flyweights return new flyweight

Page 47: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Flyweight Benefits Reduce the number of object instances at

runtime, saving memory Centralizes states for many “virtual”

objects into a single location

Page 48: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Flyweight Uses and Drawbacks The Flyweight is used when a class has

many instances, and they can all be controlled identically

A drawback of the Flyweight pattern is that once you’ve implemented it, single, logical instances of the class will not be able to behave independently from the other instances.

Page 49: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

What if both abstraction and the implementation will vary?

Page 50: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Motivation

Page 51: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

51

Structural Patterns - Bridge Intent:

Decouple an abstraction from its implementation so that the two can vary independently.

Motivation: When an abstraction can have one of several possible

implementations: inheritance An abstract class defines the interface to the abstraction, and

concrete subclasses implement it in different ways Inflexible: binds implementations to the abstraction

Example: Consider the implementation of a portable Window abstraction in a user interface toolkit. This abstraction should enable us to write applications that work on both the X Window System and IBM's Presentation Manager (PM).

Page 52: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

52

Structural Patterns - Bridge Inconvenient to extend the Window abstraction to cover different kinds of windows or new platforms.

It makes client code platform-dependent.• Whenever a client creates a window, it instantiates a

concrete class that has a specific implementation• Harder to port the client code to other platforms.

Page 53: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

53

Structural Patterns - Bridge Clients should be able to create a window without committing to a concrete implementation.

Bridge pattern: putting the Window abstraction and its implementation in separate class hierarchies.

Page 54: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bridge Pattern

Client

+Operation()

Abstraction

+OperationImp()

Implementor

RefinedAbstraction

+OperationImp()

ConcreteImplementorA

+OperationImp()

ConcreteImplementorB

implementor.OperationImp()

Page 55: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

55

Structural Patterns - Bridge

You want to avoid a permanent binding between an abstraction and its implementation. For example, when the implementation must be selected or switched at run-time.

Both the abstractions and their implementations should be extensible by subclassing. the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.

Changes in the implementation of an abstraction have no impact on clients; their code should not have to be recompiled.

In C++, you want to hide the implementation of an abstraction from clients. You want to share an implementation among multiple objects

Applicability

Page 56: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

56

Structural Patterns - Bridge Structure

(Window)

(IconWindow)

(WindowImp)

Typically the Implementor interface provides only primitive operations, and Abstraction defines higher-level operations based on these primitives.

(XWindowImp, PMWindowImp)

CollaborationsAbstraction forwards client requests to its Implementor object.

Page 57: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Participants Abstraction (Window): - defines the abstraction’s interface

- maintains a reference to an object of type Implementor Refined Abstraction (IconWindow,

DialogWindow): - extends the interface defined by Abstraction

Page 58: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Participants (continue) Implementor (WindowImp): - defines an interface for Implementation

classes. Typically, this Implementor’s interface provides only primitive methods ConcreteImplementor (XWindowImpl,

MSWindowImpl): - implements the Implementor’s interface

Page 59: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

59

Structural Patterns - Bridge

Decoupling interface and implementation The implementation of an abstraction can be configured at run-time Eliminates compile-time dependencies on the implementation Decoupling encourages layering that can lead to a better-structured system.

Improved extensibility You can extend the Abstraction and Implementor hierarchies independently.

Hiding implementation details from clients

Consequences

Page 60: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

60

Structural Patterns - Bridge Window/WindowImp Example:class Window { // windows abstraction for client applicationspublic:Window(View* contents);

// requests handled by windowvirtual void DrawContents();virtual void Open();virtual void Close();virtual void Iconify();virtual void Deiconify();

// requests forwarded to implementationvirtual void SetOrigin(const Point& at);virtual void SetExtent(const Point& extent);virtual void Raise();virtual void Lower();virtual void DrawLine(const Point&, const Point&);virtual void DrawRect(const Point&, const Point&);virtual void DrawPolygon(const Point[], int n);virtual void DrawText(const char*, const Point&);

protected:WindowImp* GetWindowImp();View* GetView();

private:WindowImp* _imp;View* _contents; // the window's contents

};

class WindowImp {public:

virtual void ImpTop() = 0;virtual void ImpBottom() = 0;virtual void ImpSetExtent(const Point&) = 0;virtual void ImpSetOrigin(const Point&) = 0;virtual void DeviceRect(Coord, Coord, Coord, Coord) = 0;virtual void DeviceText(const char*, Coord, Coord) = 0;virtual void DeviceBitmap(const char*, Coord, Coord) = 0;// lots more functions for drawing on windows...

protected:WindowImp();

}

Page 61: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

61

Structural Patterns - Bridge ICONWindowclass IconWindow : public Window {public:

// ...virtual void DrawContents();

private:const char* _bitmapName;

};

...and it implements DrawContents to draw the bitmap on the window:

void IconWindow::DrawContents() {WindowImp* imp = GetWindowImp();if (imp != 0) {

imp->DeviceBitmap(_bitmapName, 0.0, 0.0);}

}

Page 62: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

62

Structural Patterns - Bridge Draw a rectangular in the Window:void Window::DrawRect (const Point& p1, const Point& p2) {

WindowImp* imp = GetWindowImp();imp->DeviceRect(p1.X(), p1.Y(), p2.X(), p2.Y());

}

class XWindowImp : public WindowImp {public:

XWindowImp();virtual void DeviceRect(Coord, Coord, Coord, Coord);// remainder of public interface...

private:// lots of X window system-specific state, including:Display* _dpy;Drawable _winid; // window idGC _gc; // window graphic context

};

void XWindowImp::DeviceRect (Coord x0, Coord y0, Coord x1, Coord y1) {

int x = round(min(x0, x1));int y = round(min(y0, y1));int w = round(abs(x0 - x1));int h = round(abs(y0 - y1));XDrawRectangle(_dpy, _winid, _gc, x, y, w, h);

}

Page 63: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

63

Structural Patterns - Bridge How does a window obtain an instance of the right WindowImp subclass?

WindowImp* Window::GetWindowImp () {if (_imp == 0) {

_imp = WindowSystemFactory::Instance()->MakeWindowImp();}return _imp;

}

Page 64: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bridge Uses and Drawbacks Useful in graphic and windowing systems

that need to run over multiple platform Useful any time you need to vary an

interface and an implementation in different ways

Increases complexity

Page 65: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Benefits Avoid permanent binding between an

abstraction and its implementation Avoid nested generalizations Ease adding new implementations Reduce code repetition Allow runtime switching of behaviour

Page 66: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Drawbacks Double indirection

“Window” operation are implemented by subclasses of WindowImpl class. Window class must delegate the message to a WindowImpl subclass which implements the appropriate method. This will have a slight impact on performance.

Page 67: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Bridge Vs. Other Patterns Abstract Factory can create and configure

a particular Bridge

Different from Adapter Pattern: Adapter - making unrelated classes work

together - usually applied to systems after redesign

Bridge: lets abstraction and implementation vary independently - used up-front in design

Page 68: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

68

Structural Patterns - Composite

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

Intent

Page 69: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

69

Structural Patterns – Composite Motivation

Key: an abstract class that represents both primitives and their containers

Page 70: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

70

Structural Patterns - CompositeApplicability

Represents part-whole hierarchies of objects. Clients ignore the difference between compositions of objects and

individual objects. Clients treat all objects in the composite structure uniformly.

Page 71: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

71

Structural Patterns – Composite

Structure: Class Diagram

Client

Component

operation()getChild( i:int )

Leaf

operation()

Composite

operation()add( c:Component )remove( c:Component )getChild( i:int )

operation(){

for all g in children g.operation()}

*

Page 72: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

72

Structural Patterns - Composite

Structure: Object Diagram

top : Composite

top : Compositea : Leaf b : Leaf c : Leaf

d : Leaf e : Leaf

Page 73: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

73

Structural Patterns – Composite

Declares the interface for objects in the composition. Implements default behavior for the interface common to all classes, as appropriate. Declares an interface for accessing and managing its child components. Optionally defines an interface for accessing a component’s parent.

Leaf (Rectangle, Line, Text, etc.) Represents leaf objects in the composition. Defines behavior for primitive objects in the composition.

Composite (Picture) Defines behavior for components having children. Stores child components. Implements child-related operations.

Client Manipulates objects in the composition through the Component interface.

Component (Graphic)

Participants

Page 74: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

74

Structural Patterns - Composite

Clients use the Component class interface to interact with objects in the composite structure If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards requests to its child components, possibly

performing additional operations before and/or after forwarding.

Collaborations

Page 75: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

75

-root---Leaf A---Leaf B---Composite X-----Leaf XA-----Leaf XB---Leaf C

using System;using System.Collections;

namespace DoFactory.GangOfFour.Composite.Structural{

  // MainApp test application

  class MainApp  {    static void Main()    {      // Create a tree structure       Composite root = new Composite("root");      root.Add(new Leaf("Leaf A"));      root.Add(new Leaf("Leaf B"));

      Composite comp = new Composite("Composite X");      comp.Add(new Leaf("Leaf XA"));      comp.Add(new Leaf("Leaf XB"));

      root.Add(comp);      root.Add(new Leaf("Leaf C"));

      // Add and remove a leaf       Leaf leaf = new Leaf("Leaf D");      root.Add(leaf);      root.Remove(leaf);

      // Recursively display tree       root.Display(1);

      // Wait for user       Console.Read();    }  }

// "Component"   abstract class Component  {protected string name;

    // Constructor     public Component(string name)    {this.name = name;}

    public abstract void Add(Component c);    public abstract void Remove(Component c);    public abstract void Display(int depth);  }

  // "Composite"   class Composite : Component  {private ArrayList children = new ArrayList();

    // Constructor     public Composite(string name) : base(name) {  }

    public override void Add(Component component)    {children.Add(component);}

    public override void Remove(Component component)    {children.Remove(component);}

    public override void Display(int depth)    {Console.WriteLine(new String('-', depth) + name);

      // Recursively display child nodes       foreach (Component component in children)      {component.Display(depth + 2);}    }  }

 // "Leaf"   class Leaf : Component  {// Constructor     public Leaf(string name) : base(name) {  }

    public override void Add(Component c)    {Console.WriteLine("Cannot add to a leaf");}

    public override void Remove(Component c)    {Console.WriteLine("Cannot remove from a leaf");}

    public override void Display(int depth)    {Console.WriteLine(new String('-', depth) + name);}  }}

http://www.dofactory.com/Patterns/PatternComposite.aspx

Page 76: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

76

Structural Patterns - Composite

Benefits It makes it easy to add new kinds of components It makes clients simpler, since they do not have to know if they are dealing with a leaf or a composite component

Liabilities It makes it harder to restrict the type of components of a composite

Consequences

Page 77: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

What if an Object shouldn’t be accessed directly?

Page 78: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

78

Structural Patterns - Proxy

Provide a surrogate or placeholder for another object to control access to it.

Applicability A more sophisticated reference than a simple pointer is needed Remote proxy — provides a local representative for an object in a different

address space. Virtual proxy — creates expensive objects on demand. Protection proxy — controls access to the original object. Smart reference — replacement for a bare pointer

Reference counting: manage object lifetime Loading persistent object on access Transactional locking

Intent

Page 79: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

79

Structural Patterns - Proxy

Class Diagram

Client

<<abstract>>Subject

request()...

RealSubject

request()...

Proxy

request()...

request(){

... realSubject.request()

...}

Page 80: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

80

Structural Patterns - Proxy

Object Diagram

aClient:

aProxy : Proxy

subject : RealSubject

Page 81: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

81

Structural Patterns - Proxy

Subject: Defines the common interface for RealSubject and Proxy. Proxy:

Maintains reference to real subject Can be substituted for a real subject Controls access to real subject May be responsible for creating and deleting the real subject Special responsibilities

Marshaling for remote communication Caching data Access validation

RealSubject: Defines the real object that the proxy represents. Client: Accesses the RealSubject through the intervention of the Proxy.

Participants

Proxy forwards requests to RealSubject when appropriate, depending on the kind of proxy.

Collaborations

Page 82: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Example using Proxy Pattern

AppCodeRemoteObjectProxyDeals with communicationLogicCaches static information

RemoteObject

Page 83: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Consequences of using Proxy Introduces a level of indirection in

accessing objects

Indirection provides flexibility

Incurred cost on additional object and computations

Page 84: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Proxy Vs. Other Patterns Adapter changes interface, Proxy provides

the same interface protection proxy implements subset of

interface - may deny access to certain functions

Proxy controls functionality

Page 85: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Design Principle

Dependency Inversion: Program to an interface, not an implementation.

Favor composition over inheritance

Lesson: knowing major OO concepts like encapsulation inheritance, polymorphism does not automatically make a good designer

A design guru thinks about how to create flexible designs that are maintainable and that can cope with change.

Page 86: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Dealing with change What is going to change?

How to deal with it? That is why we learn design patterns All patterns provide a way to let some part of a

system vary independently of all other parts

Page 87: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Design Principle

Information Hiding: Identify the aspects of your application that vary and separate them from what stays the same.

Take what varies and “extract” it so it won’t affect the rest of your code

The result? Fewer unintended consequences from code changes and more flexibility in your system

Page 88: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Composition vs. inheritance They both are ways to re-use functionality Inheritance:

Re-use functionality of parent class Statically decided (inheritance decided at run time) Weakens encapsulation

Composition: Re-use functionality of objects collected at run-

time Invoked through the interface More dynamic: multiple types with same interface Black-box re-use

Page 89: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Composition vs. inheritance (2) Composition allows more behavior flexibility

When possible use it instead of inheritance

Inheritance is still a quick way to design new components that are variants of existing ones

Over-use of inheritance creates bloated hierarchies Code is more difficult to maintain Unnecessary baggage for many classes

Composition drawback: it becomes harder to understand the behavior of a program by looking only at its source code Semantics of interaction are decided at run-time

Page 90: 1 Structural Patterns  How classes and objects are composed to form larger structures  Structural class patterns: use inheritance to compose interfaces.

Words of wisdom … OO design principles So far:

The main goal (almost not evident) of design is to: minimize coupling and maximize cohesion

Identify the aspects of your application that vary and separate them from what stays the same

Program to an interface , not an implementation. Favor composition over inheritance The Open-Closed Principle:

Classes should be open for extension, but closed for modification