58
1 Traditional Design Patterns -- I These slides are mainly based on: Tutorial slides by John Vlissides, see http://www.research.ibm.com/designpatter ns/pubs/dp-tutorial.pdf • Text © 1994-1999 by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides • Diagrams © 1995 by Addison-Wesley Publishing Company • Note: Compared to the original tutorial by John Vlissides, the diagram notation have been upgraded from OMT to UML and some text has been updated

1 Traditional Design Patterns -- I These slides are mainly based on: –Tutorial slides by John Vlissides, see

Embed Size (px)

Citation preview

1

Traditional Design Patterns -- I

• These slides are mainly based on:– Tutorial slides by John Vlissides, see

http://www.research.ibm.com/designpatterns/pubs/dp-tutorial.pdf

• Text © 1994-1999 by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

• Diagrams © 1995 by Addison-Wesley Publishing Company

• Note: Compared to the original tutorial by John Vlissides, the diagram notation have been upgraded from OMT to UML and some text has been updated

2

Overview

Motivation and Concept– Observer

• Example: WYSIWYG Editor– Composite– Strategy– Decorator– Abstract Factory

3

Analysis vs. Design

• Analysis– Domain level - modeling “real world” objects– Many domain objects will not make into the design– Domain structures usually make poor design structures

• Design– Assigning responsibilities to object– Taking “illities” (maintainability, reusability, etc.) and

portability into account– Devising mechanisms– But how to get to the design objects and mechanisms?

4

Motivation and Concept

• OOD methods emphasize design notations– Fine for specification, documentation

• But OOD is more than just drawing diagrams– Good draftsmen good designers

• Good OO designers rely on lots of experience– At least as important as syntax

• Most powerful reuse is design reuse– Match problem to design experience

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

5

Motivation and Concept

• OO systems exploit recurring design structures that promote– Abstraction– Flexibility– Modularity– Elegance

• Therein lies valuable design knowledge• Problem: capturing, communicating, and applying

this knowledge

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

6

What Is a Design Pattern?

• A design pattern– Is a common solution to a recurring problem in

design– Abstracts a recurring design structure– Comprises class and/or object

• Dependencies• Structures• Interactions• Conventions

– Names & specifies the design structure explicitly– Distils design experience

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

7

What Is a Design Pattern?

• A design pattern has 4 basic parts:– 1. Name– 2. Problem– 3. Solution– 4. Consequences and trade-offs of application

• Language- and implementation-independent• A “micro-architecture”• Adjunct to existing methodologies (Unified, OMT, etc.)• No mechanical application

– The solution needs to be translated into concrete terms in the application context by the developer

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

8

Example: Observer

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

9

Goals

• Codify good design– Distil and disseminate experience– Aid to novices and experts alike– Abstract how to think about design

• Give design structures explicit names– Common vocabulary– Reduced complexity– Greater expressiveness

• Capture and preserve design information– Articulate design decisions succinctly– Improve documentation

• Facilitate restructuring/refactoring– Patterns are interrelated– Additional flexibility

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

10

Design Pattern Catalogues

• GoF (“the gang of four”) catalogue– “Design Patterns: Elements of Reusable Object-

Oriented Software,” Gamma, Helm, Johnson, Vlissides, Addison-Wesley, 1995

• POSA catalogue– Pattern-Oriented Software Architecture,

Buschmann, et al.; Wiley, 1996

• …

11

Classification of GoF Design PatternCreational Structural Behavioral

Factory Method

Abstract Factory

Builder

Prototype

Singleton

Adapter

Bridge

Composite

Decorator

Flyweight

Facade

Proxy

Interpreter

Template Method

Chain of Responsibility

Command

Iterator

Mediator

Memento

Observer

State

Strategy

Visitor

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

12

Design Pattern Template (First Half )

• Name (and classification)• Intent

– Short description of pattern and its purpose

• Also known as– Other names that people have for the pattern

• Motivation– Motivating scenario demonstrating pattern's use

• Applicability– Circumstances in which pattern applies

• Structure– Graphical representation of the pattern– GoF used OMT and interaction diagrams (a precursor to UML)

• Participants– Participating classes and/or objects and their responsibilities

• ...

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

13

Design Pattern Template (Second Half )

• ...• Collaborations

– How participants cooperate to carry out their responsibilities

• Consequences– The results of application, benefits, liabilities

• Implementation– Implementation pitfalls, hints, or techniques, plus any language-dependent

issues

• Sample code– Sample implementations in C++, Java, C#, Smalltalk, etc.

• Known uses– Examples drawn from existing systems

• Related patterns– Discussion of other patterns that relate to this one

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

14

Observer (Behavioral)

• Intent– Define a one-to-many dependency between objects so that when

one object changes state, all its dependents are notified and updated automatically

• Applicability– When an abstraction has two aspects, one dependent on the other

– When a change to one object requires changing others, and you don't know how many objects need to be changed

– When an object should notify other objects without making assumptions about who these objects are

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

15

Observer (Cont'd)

• Structure

+attach(in o : Observer)+detach(in o : Observer)+notify()

Subject

+update()

Observer

+getState()

-subjectState

ConcreteSubject

+update()

-observerState

ConcreteObserver

1

-observers

*

{observerState = subject.getState() }

{return subjectState }

{for all o in observers{ o.update() } }

-subject

1 *

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

16

Observer (Cont'd)

• Consequences+ Modularity: subject and observers may vary independently+ Extensibility: can define and add any number of observers+ Customizability: different observers provide different views of

subject– Unexpected updates: observers don't know about each other– Update overhead: might need hints

• Implementation– Subject-observer mapping– Dangling references– Avoiding observer-specific update protocols: the push and push/pull

models– Registering modifications of interest explicitly

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

17

Observer (Cont'd)

• Known uses– Smalltalk model-view-controller (MVC)

– Interviews (subjects and views)

– Andrew (data objects and views)

• Benefits– Design reuse

– Uniform design vocabulary

– Enhance understanding, restructuring

– Basis for automation

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

18

Observer (Cont'd)

• Structure

+attach(in o : Observer)+detach(in o : Observer)+notify()

Subject

+update()

Observer

+getState()

-subjectState

ConcreteSubject

+update()

-observerState

ConcreteObserver

1

-observers

*

{observerState = subject.getState() }

{return subjectState }

{for all o in observers{ o.update() } }

-subject

1 *

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

19

Schematic Observer Example

Subject

Observers

20

Observer - Sample Code

class Subject { public:      virtual ~Subject();      virtual void Attach(Observer*);      virtual void Detach(Observer*);      virtual void Notify(); protected:      Subject(); private:      List<Observer*> *_observers; };

void Subject::Attach (Observer* o) {      _observers->Insert(_observers->end(), o); }

void Subject::Detach (Observer* o) {      _observers->remove(o); }

void Subject::Notify () {      ListIterator<Observer*>i(_observers);

     for (i.First(); !i.IsDone(); i.Next()) {           i.CurrentItem()->Update(this);      } }

class Observer { public:      virtual ~Observer();      virtual void Update(Subject* theChangeSubject) = 0; protected:      Observer(); };

class ClockTimer : public Subject { public:      ClockTimer();      virtual int GetHour();      virtual int GetMinute();      virtual int GetSecond();      void Tick(); }; void ClockTimer::Tick() {      // update internal time-keeping state      // ...      Notify(); }

21

Observer – Sample Codeclass DigitalClock: public Observer {

public:      DigitalClock(ClockTimer *);      ~DigitalClock();     

void Update(Subject *);      void Draw(); private:      ClockTimer *_subject; };

DigitalClock::DigitalClock (ClockTimer *s) {      _subject = s;      _subject->Attach(this); }

DigitalClock::~DigitalClock () {      _subject->Detach(this); }

void DigitalClock::Update (Subject *theChangedSubject) {      if(theChangedSubject == _subject)           draw(); }

void DigitalClock::Draw () {      int hour = _subject->GetHour();      int minute = _subject->GetMinute();      int second = _subject->GetSecond();

     // draw operation        }

class AnalogClock: public Observer { public:      AnalogClock(ClockTimer *);      ~AnalogClock();      void Update(Subject *);      void Draw(); private:      ClockTimer *_subject; };

int main(void) {      ClockTimer *timer = new ClockTimer;      AnalogClock *analogClock = new AnalogClock(timer);      DigitalClock *digitalClock = new DigitalClock(timer);      timer->Tick();      return 0; }

26

Document Structure

• Solution: Recursive composition

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

30

Schematic Observer Example

Subject

Observers

31

Composite (Structural)

• Intent– Treat individual objects and multiple, recursively-

composed objects uniformly

• Applicability– Objects must be composed recursively,– And there should be no distinction between individual

and composed elements,– And objects in the structure can be treated uniformly– Part-Whole hierarchy of objects. – Constant handling of objects as groups or individuals

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

32

Composite (Cont'd)

• Structure+operation()+add(in c : Component)+remove(in c : Component)+getChild(in i : int)

Component

+operation()

Leaf

1

-children

*

+operation()+add(in c : Composite)+remove(in c : Composite)+getChild(in i : int)

Composite

{ forall g in childreng.operation(); }

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

33

Composite (Cont'd)

• Consequences+ Uniformity: treat components the same regardless of

complexity+ Extensibility: new Component subclasses work wherever old

ones do– Overhead: might need prohibitive numbers of objects

• Implementation– Do Components know their parents?– Uniform interface for both leaves and composites?– Don't allocate storage for children in Component base class– Responsibility for deleting children

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

34

Composite (Cont'd)

• Known Uses– ET++ VObjects– InterViews Glyphs, Styles– Unidraw Components, MacroCommands

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

35

Composite - Example

36

Composite – Sample Code

Currency CompositeEquipment::NetPrice() {    Iterator<Equipment*>* i     = getIterator();    Currency              total = 0;   

for (i->First(); !i->IsDone(); i->Next())      total += i->CurrentItem()->NetPrice(); 

  delete i;    return total;   }

// and in the client code … (e.g. in main)

Cabinet* cabinet = new Cabinet("PC Cabinet");  Chassis* chassis = new Chassis("PC Chassis");  cabinet->Add( chassis );  Bus*     bus     = new Bus    ("MCA Bus");  bus    ->Add( new Card("16Mbs Token Ring") );  chassis->Add( bus );  chassis->Add( new FloppyDisk("3.5 floppy") );  cout << chassis->NetPrice() << endl;

42

Strategy (Behavioral)

• Intent– Define a family of algorithms, encapsulate each

one, and make them interchangeable to let clients and algorithms vary independently

• Applicability– When an object should be configurable with

one of several algorithms,and all algorithms can be encapsulated,and one interface covers all encapsulations

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

43

Strategy (Cont'd)

• Structure

+contextInterface()

Context (Composition)

+algorithmInterface()

Strategy (Compositor)

+algorithmInterface()

ConcreteStrategyA

+algorithmInterface()

ConcreteStrategyB

+algorithmInterface()

ConcreteStrategyC

1 1

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

44

Strategy (Cont'd)

• Consequences+ Greater flexibility, reuse+ Can change algorithms dynamically– Strategy creation & communication overhead– Inflexible strategy interface

• Implementation– Exchanging information between a strategy and its context– Static strategy selection via templates

• Known uses– Interviews text formatting– RTL register allocation & scheduling strategies– Et++SwapsManager calculation engines

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

45

Strategy - Example

46

Strategy – Sample Codeclass ConcreteContext : public Context{   public:   ConcreteContext();     ConcreteContext(Strategy<class T> *);     ConcreteContext(const ConcreteContext &);     int array[10]; Strategy *thisStratergy; Boolean aggregation; void execute(); void attachStrategy(Strategy *s);};

template <class T> class Print : public Strategy<T>{   public:     virtual void doAlgorithm(T* const);      Print<class T> *clone(); };

template <class T> class DecreasePrint : public Strategy<T>{   public:     virtual void doAlgorithm(T* const cont);         void quicksortD(int array[], int l, int r);     DecreasePrint<class T> *clone();     int array[10];     };

template <class T> void IncreasePrint<T>::doAlgorithm( T* const cont) {   for (int i=0; i<10; i++)          array[i] = cont->array[i];        quicksortI(array, 0, 9);        printf("INCREASING ORDER\n");        for (int i=0; i<10; i++)           ::printf("Element no %d = %d\n", i, array[i]);}

47

Strategy – Sample Code

template <class T>

void DecreasePrint<T>::doAlgorithm(T* const cont){

for (int i=0; i<10; i++)         

array[i] = cont->array[i];       

quicksortD(array, 0, 9);       

::printf("DECREASING ORDER\n");

for (int i=0; i<10; i++)          

::printf("Element no %d = %d\n", i, array[i]);

}

void Context::execute(){   if(thisStrategy){     thisStrategy->doAlgorithm((T *)this); }   else {     ::printf("Error: there is no strategy attached to the context\n");     ::printf("An exeception has been thrown\n");     throw "Error: there is no stategy attach to the context";   } }

void Context::attachStrategy(Strategy<class T> * anotherStrategy){   if (aggregation)     delete thisStrategy;   thisStrategy =  anotherStrategy; }

48

Strategy - Sample Code

Context::Context(const Context &t)

{  

if(t.aggregation){  

  thisStrategy = t.thisStrategy->clone();    

aggregation = true;  

}

else

{ thisStrategy = t.thisStrategy;    

aggregation = false;  

}

}

49

Strategy – Sample Codemain(int argc, char **argv){ ConcreteContext * context1 = new ConcreteContext(); context1->attachStrategy((Strategy<T> *)(new Print<ConcreteContext>())); context1->execute(); ::printf("*****************\n"); ConcreteContext * context2 = new ConcreteContext(*context1); // Copy constructor context1->attachStrategy((Strategy<T> *)(new IncreasePrint<ConcreteContext>())); context1->execute(); ::printf("*****************\n"); context1->removeStrategy(); context1->attachStrategy((Strategy<T> *)(new DecreasePrint<ConcreteContext>())); context1->execute(); context1->removeStrategy(); delete context1; ::printf("*****Context2******\n"); context2->execute(); context2->removeStrategy(); delete context2; :: printf("\n Testing Aggregation \n\n"); context1 = new ConcreteContext( (Strategy<T> *)(new IncreasePrint<ConcreteContext>())); context1->execute(); ::printf("*****************\n"); context2 = new ConcreteContext(*context1); delete context1; context2->execute(); delete context2; }

55

Decorator (Structural)

• Intent– Augment objects with new responsibilities

• Applicability– When extension by subclassing is impractical– For responsibilities that can be withdrawn

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

56

Decorator Diagram

• Structure

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

+operation()

Component (Glyph)

+operation()

ConcreteComponent

+operation()

Decorator (MonoGlyph)

+operation()

-addedState

ConcreteDecoratorA

+operation()+addedBehavior()

ConcreteDecoratorB

1

-component

1

{ component-> component.operation(); }

{ super.operation(); addedBehavior(); }

57

Decorator - Diagram

58

Decorator Overview

• A Decorator, also known as a Wrapper, is an object that has an interface identical to an object that it contains. Any calls that the decorator gets, it relays to the object that it contains, and adds its own functionality along the way, either before or after the call.

• Therefore, the Decorator Pattern is used for adding additional functionality to a particular object as opposed to a class of objects.

• It is easy to add functionality to an entire class of objects by subclassing an object, but it is impossible to extend a single object this way. With the Decorator Pattern, you can add functionality to a single object and leave others like it unmodified.

59

Decorator Comments• The Decorator pattern gives you a lot of flexibility, since

you can change what the decorator does at runtime, as opposed to having the change be static and determined at compile time by subclassing.

• Since a Decorator complies with the interface that the object that it contains, the Decorator is indistinguishable from the object that it contains.  That is, a Decorator is a concrete instance of the abstract class, and thus is indistinguishable from any other concrete instance, including other decorators.   

• This can be used to great advantage, as you can recursively nest decorators without any other objects being able to tell the difference, allowing a near infinite amount of customization.

60

Decorator (Cont'd)

• Consequences+ Responsibilities can be added/removed at run-time+ Avoids subclass explosion+ Recursive nesting allows multiple responsibilities– Interface occlusion– Identity crisis

• Implementation– Interface conformance– Use a lightweight, abstract base class for Decorator– Heavyweight base classes make Strategy more attractive

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

61

Decorator (Cont'd)

• Known Uses– Embellishment objects from most OO-GUI

toolkits– ParcPlace PassivityWrapper– InterViews DebuggingGlyph

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

65

Decorator Example

66

Decorator Example

class Book extends LibItem{ String author; intnoCopies; intonShelf; String title; public Book(String t, String a, int c){ title = t; noCopies= c; author = a; onShelf= c; } public String getTitle() { return title; } public int getCopies() { return noCopies; }

public int copiesOnShelf() { return onShelf; } public void decCopiesOnShelf() { onShelf--; } public void incCopiesOnShelf() { onShelf++; } public String getAuthor() { return author; } public void borrowItem(String borrower) { System.out.println("borrow–in Book"); } public void returnItem(String borrower) { } public void reserve(String reserver) { }} /* End class Book */

67

Decorator Exampleabstract class Decorator extends LibItem{ LibItem item; public Decorator(LibItem li) { item = li; } public String getTitle() { return item.getTitle(); }// Following methods are // similarly implemented public String getAuthor() {... public intgetCopies() { ... public intcopiesOnShelf() { ... public void decCopiesOnShelf() { item.decCopiesOnShelf(); } // and similarly... public void incCopiesOnShelf() {...

68

Decorator Example

69

Decorator Example - (client)// Non borrowable, non reservablebookLibItem b1 = new Book("A", "B", 1);// BorrowablevideoLibItem v1 = new BorrowableDec(new Video("V", 3));// borrow unborrowableitem -copies should stay 1b1.borrowItem("Bob");System.out.println("Copiesof book = " +b1.copiesOnShelf());// borrow video -copies decremented to 2v1.borrowItem("Fred");System.out.println("Copiesof video = " +v1.copiesOnShelf());//make book borrowableand borrow it -copies = 0LibItem b2 = new BorrowableDec(b1);b2.borrowItem("Bob");System.out.println("Copiesof book = " +b2.copiesOnShelf());// make book reservableLibItem b3 = new ReservableDec(b2);b3.reserve("Alice");b3.returnItem("Bob");// book returned -back to 1 copySystem.out.println("Copiesof book = " +b3.copiesOnShelf());// Not reserved for Jane -still 1 copyb3.borrowItem("Jane");System.out.println("Copiesof book = " +b3.copiesOnShelf());// Okay Alice can borrow -down to 0b3.borrowItem("Alice");System.out.println("Copiesof book = " +b3.copiesOnShelf());

70

Decorator Diagram

• Structure

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

+operation()

Component (Glyph)

+operation()

ConcreteComponent

+operation()

Decorator (MonoGlyph)

+operation()

-addedState

ConcreteDecoratorA

+operation()+addedBehavior()

ConcreteDecoratorB

1

-component

1

{ component-> component.operation(); }

{ super.operation(); addedBehavior(); }

71

Overview

• Motivation and Concept– Observer

• Example: WYSIWYG Editor– Composite - Document Structure– Strategy - Formatting– Decorator - EmbellishmentAbstract Factory - Multiple Look&Feels

76

Abstract Factory (Creational)

• Intent– Create families of related objects without

specifying class names

• Applicability– When clients cannot anticipate groups of

classes to instantiate

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

77

Abstract Factory (Cont'd)

• Structure+createProductA()+createProductB()

AbstractFactory

AbstractProductB+createProductA()+createProductB()

ConcreteFactory1

+createProductA()+createProductB()

ConcreteFactory2

ProductB1 ProductB2

AbstractProductA

ProductA1 ProductA2

Client

* *

*

*

*

*

«instantiate»«instantiate»

«instantiate»

«instantiate»

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

78

Abstract Factory - Example

public class MazeFactory { public MazeFactory() {...} public Maze makeMaze(){ return new Maze(); } public Room makeRoom(int n) { return new Room(n); } public Wall makeWall() { return new Wall(); } public Door makeDoor(Room r1, Room r2) { return new Door(r1, r2); }};

public class MazeGame {// ... public Maze createMaze (MazeFactory factory) { Maze aMaze = factory.makeMaze(); Room r1 = factory.makeRoom(1); Room r2 = factory.makeRoom(2); Door theDoor = factory.makeDoor(r1, r2); aMaze.addRoom(r1); aMaze.addRoom(r2); r1.setSide(MapSite.NORTH, factory.makeWall()); r1.setSide(MapSite.EAST, theDoor); r1.setSide(MapSite.SOUTH, factory.makeWall()); r1.setSide(MapSite.WEST, factory.makeWall()); r2.setSide(MapSite.NORTH, factory.makeWall()); r2.setSide(MapSite.EAST, factory.makeWall()); r2.setSide(MapSite.SOUTH, factory.makeWall(); r2.setSide(MapSite.WEST, theDoor); return aMaze; }}

79

Abstract Factory - Examplepublic class EnchantedMazeFactory extends MazeFactory {

public EnchantedMazeFactory() {...} public Room makeRoom(int n) { return new EnchantedRoom(n, new Spell()); } public Door makeDoor(Room r1, Room r2) { return new DoorNeedingSpell(r1, r2); } }

public class BombedMazeFactory extends MazeFactory {public BombedMazeFactory() {...}

public Wall makeWall(){ return new BombedWall(); } public Room makeRoom(int n){ return new RoomWithABomb(n); }}

80

Abstract Factory - Client

MazeGame game; // The instance of a game.……….Maze aMaze; // A reference to a maze. switch(choice) {

case ENCHANTED: { EnchantedMazeFactory factory = new EnchantedMazeFactory(); aMaze = game.createMaze(factory); break;

}case BOMBED: { BombedMazeFactory factory = new BombedMazeFactory(); aMaze = game.createMaze(factory); break;}

}

82

Abstract Factory (Cont'd)

• Consequences+ Flexibility: removes type dependencies from clients+ Abstraction: hides product's composition– Hard to extend factory interface to create new products

• Implementation– Parameterization as a way of controlling interface size– Configuration with Prototypes

• Known Uses– InterViews Kits– ET++ WindowSystem

© E

. Gam

ma,

R. H

elm

, R. J

ohns

on, J

. Vlis

side

s an

d A

ddis

on-W

esle

y

83

Overview

• Motivation and Concept– Observer

• Example: WYSIWYG Editor– Composite - Document Structure– Strategy - Formatting– Decorator - Embellishment– Abstract Factory - Multiple Look&Feels