+ All Categories
Home > Documents > Chapter 2

Chapter 2

Date post: 13-Jan-2016
Category:
Upload: barth
View: 43 times
Download: 5 times
Share this document with a friend
Description:
Chapter 2. Design Principles and Design Patterns. Object-Oriented Design Principles. OO Design vs. OO Programming. Object-Oriented Design a method for decomposing software architectures based on the objects every system or subsystem manipulates - PowerPoint PPT Presentation
Popular Tags:
322
Chapter 2 Design Principles and Design Patterns
Transcript
Page 1: Chapter 2

Chapter 2

Design Principles and Design Patterns

Page 2: Chapter 2

Object-Oriented Design Principles

Page 3: Chapter 2

OO Design vs. OO Programming

Object-Oriented Design – a method for decomposing software architectures

– based on the objects every system or subsystem manipulates

– relatively independent of the programming language used

Object-Oriented Programming– construction of software systems as

• Structured collection of Abstract Data Types (ADT)

• Inheritance

• Polymorphism

– concerned with programming languages and implementation issues

Page 4: Chapter 2

Polymorphism

Behavior promised in the public interface of superclass objects implemented by subclass objects

– in the specific way required for the subclass

Why Is this Important? – Allow subclasses to be treated like instances of their superclasses

– Flexible architectures and designs• high-level logic defined in terms of abstract interfaces• relying on the specific implementation provided by subclasses • subclasses can be added without changing high-level logic

Page 5: Chapter 2

Signs of Rotting Design

Rigidity ( 僵硬性 ) – code difficult to change

– management reluctance( 拒絶 ) to change anything becomes policy

Fragility ( 易碎性 ) – even small changes can cause cascading effects

– code breaks in unexpected places

Immobility( 固定性 ) – code is so tangled( 糾結 ) that it's impossible to reuse anything

Viscosity( 黏滯性 )

– much easier to hack( 亂砍 ) than to preserve original design

Page 6: Chapter 2

Causes of Rotting Design Changing Requirements

– is inevitable– "All systems change during their life-cycles. This must be borne in mind when

developing systems expected to last longer than the first version". (I. Jacobson, OOSE, 1992)

Dependency Management– the issue of coupling and cohesion– It can be controlled!

• create dependency firewalls• see DIP example

Page 7: Chapter 2

Principle #1

The Open-Closed Principle:

Page 8: Chapter 2

Open-Closed Principle (OCP) "Software Systems change during their life time"

– both better designs and poor designs have to face the changes;

– good designs are stable

Software entities should be open for extension, but closed for modification

B. Meyer, 1988 / quoted by R. Martin, 1996

Be open for extension module's behavior can be extended

Be closed for modification source code for the module must not be changes

Modules should be written so they can be extended

without requiring them to be modified

Page 9: Chapter 2

The Open-Closed Principle OCP attacks software rigidity and fragility!

– When one change causes a cascade of changes The Open-Closed Principle (OCP) states:

– we should attempt to design modules that never need to be changed.

– extend the behavior of the system by adding new code. We do not modify old code

Modules that conform to OCP meet two criteria: Open for Extension - the behavior can be extended to meet new requirements Closed for Modification - the source code of the module is not allowed to change

Page 10: Chapter 2

Abstraction is the Key!

Abstraction– “Denotes the essential characteristics of an object that

distinguish it from all other kinds of objects and thus provides crisply defined conceptual boundaries relative to the perspective of the viewer” -- Grady Booch

Fundamental technique of dealing with complexity Focuses on the outside view of an object and separates

object’s behavior from its implementation

Page 11: Chapter 2

Encapsulation

Encapsulation – “Mechanism used to hide the data, internal structure, and

implementation details of an object. All interaction with the object is through a public interface of operations” -- Craig Larman

Classes should be opaque( 不透明 )

Classes should not expose their internal implementation details

Page 12: Chapter 2

Information Hiding in Java

Use private members and appropriate accessors and mutators when possible

Example:Replace

• public float accuracy;

With private float accuracy; public float getAccuracy ( ) { return (accuracy);} public void setAccuracy (float acc) { accuracy = acc; }

Page 13: Chapter 2

Example: “Closed Client”

Client and Server are concrete classes Client class uses Server class If Client object wants to switch to a different Server object,

what would need to happen?

Client Server

Client code needs to be modified to name the new Server class

Page 14: Chapter 2

Example : “Open Client”

How is this “open” ?

Client AbstractServer

Server

Since the Client depends on the AbstractServer, we can simply switch the Client to using a different Server, by providing a new Server implementation. Client code is unaffected!

Page 15: Chapter 2

Open the door ...

How to make the Car run efficiently with a TurboEngine? Only by changing the Car!

– ...in the given design

Page 16: Chapter 2

... But Keep It Closed!

A class must not depend on a concrete class! It must depend on an abstract class ... ...using polymorphic dependencies (calls)

Page 17: Chapter 2

Strategic Closure "No significant program can be 100% closed "

R.Martin, “The Open-Closed Principle,” 1996

– Closure not complete but strategic

Use abstraction to gain explicit closure– provide class methods which can be dynamically invoked

• to determine general policy decisions

– design using abstract ancestor classes

Use "Data-Driven" approach to achieve closure – place volatile policy decisions in a separate location

• e.g. a file or a separate object

– minimizes future change locations

Page 18: Chapter 2

OCP Heuristics

Changes to public data are always at risk to “open” the module– They may have a rippling effect requiring changes at many unexpected

locations;

– Errors can be difficult to completely find and fix. Fixes may cause errors elsewhere.

Make all object-data privateNo Global Variables!

Page 19: Chapter 2

OCP Heuristics (2)

RTTI is ugly and dangerous– If a module tries to dynamically cast a base class pointer to several derived

classes, any time you extend the inheritance hierarchy, you need to change the module

– recognize them by type switch-es or if-else-if structures

Not all these situations violate OCP all the time– when used only as a "filter"

RTTI is Ugly and Dangerous!

Page 20: Chapter 2

Another OCP Example Consider the following method:

The job of the above method is to total the price of all parts in the specified array of parts.

Does this conform to OCP?

• YES! If Part is a base class or an interface and polymorphism is being used, then this class can easily accommodate new types of parts without having to be modified!

Page 21: Chapter 2

OCP Example (contd.) But what if the Accounting Department now decreed that motherboard parts

and memory parts have a premium applied when figuring the total price?

Would the following be a suitable modification? Does it conform to OCP?

Page 22: Chapter 2

OCP Example - OCP Conformance

No! Every time the Accounting Department comes out with a new pricing policy, we have to modify totalPrice ( ) method. This is not “Closed for modification”

• These policy changes have to be implemented some place, so what is a solution?

• Version 1 - Could incorporate the pricing policy in getPrice ( ) method of Part.

Page 23: Chapter 2

OCP Example (contd.) Here are example Part and Concrete Part classes:

Add method

Code in concrete classes

•Does this work? Is it “closed for modification”?–No. We must now modify each subclass of Part whenever the pricing policy changes!

Page 24: Chapter 2

How to make it “Closed for Modification”

Better idea - have a PricePolicy class which can be used to provide different pricing policies:

Page 25: Chapter 2

OCP Example (contd.)

Page 26: Chapter 2

OCP Example (contd.)

With this solution we can dynamically set pricing policies at run time by changing the PricePolicy object that an existing Part object refers to.

Any other solution?

Both price of a Part and its associated PricePolicy could be stored in a database.

Page 27: Chapter 2

Single Choice Principle

Corollary to OCP

The Single Choice Principle:

Whenever a software system must support a set of alternatives, ideally only one class in the system

knows the entire set of alternatives!

Page 28: Chapter 2

The Open-Closed PrincipleThings to Remember OCP is the heart of OO design

– Well designed code can be extended without modification

– Primary mechanisms: abstraction and polymorphism (and inheritance hierarchies)

– Conformance to this principle yields the greatest level of reusability and maintainability

It is not possible to have all modules of a software system satisfy the OCP, but we need to attempt to minimize the number of modules that do not satisfy it.

Page 29: Chapter 2

Principle #2

The Liskov Substitution Principle:

Page 30: Chapter 2

The Liskov Substitution Principle

Inheritance should ensure that any property proved about supertype objects also holds for subtype objects

B. Liskov, 1987

The key of OCP: Abstraction and Polymorphism Implemented by inheritance How do we measure the quality of inheritance?

Functions that use pointers or references to base classesmust be able to use objects of derived classes

without knowing it.R. Martin, 1996

Page 31: Chapter 2

The Liskov Substitution Principle

The Liskov Substitution Principle (LSP) seems obvious given polymorphism

For example:

public void drawShape (Shape s) { // code here }

The drawShape method should work with any subclass of the Shape superclass (or, if Shape is a Java interface, it should work with any class that implements the Shape interface)

So what is the big deal with LSP?

Page 32: Chapter 2

The Liskov Substitution Principle

If a function does not satisfy the LSP, then it probably makes explicit reference to some or all of the subclasses of its superclass. Such a function also violates the Open-Closed Principle, since it may have to be modified whenever a new subclass is created.

Page 33: Chapter 2

Inheritance Appears Simple

class Bird { // has beak, wings,... public void fly() {…}; // Bird can fly};

class Parrot extends Bird { // Parrot is a bird public void mimic() {…}; // Can Repeat words...};

// ...Parrot mypet;mypet.mimic(); // my pet being a parrot can Mimic()mypet.fly(); // my pet “is-a” bird, can fly

Page 34: Chapter 2

Penguins Fail to Fly!class Penguin extends Bird {

public void fly() {

error (“Penguins don’t fly!”); }

};

void PlayWithBird (Bird abird) {

abird.fly(); // OK if Parrot.

// if bird happens to be Penguin...OOOPS!!

}

Does not model: “Penguins can’t fly”

It models “Penguins may fly, but if they try it is error”

Run-time error if attempt to fly not desirable

Think about Substitutability - Fails LSP

Page 35: Chapter 2

Design by Contract Advertised Behavior of an object:

– advertised Requirements (Preconditions)

– advertised Promises (Postconditions)

When redefining a method in a derivate class, you may only replace its precondition by a weaker one, and

its postcondition by a stronger oneB. Meyer, 1988

Derived class services should require no more and promise no less

int Base::f(int x);// REQUIRE: x is odd// PROMISE: return even int

int Derived::f(int x);// REQUIRE: x is int// PROMISE: return 8

Page 36: Chapter 2

Square IS-A Rectangle?

Should I inherit Square from Rectangle?

Square

?

Page 37: Chapter 2

Another LSP Example

Consider the following Rectangle class:

// A very nice Rectangle class public class Rectangle { private double width; private double height;

public Rectangle (double w, double h) { width = w; height = h; } public double getWidth ( ) { return width;} public double getHeight ( ) { return height;} public void setWidth (double w) { width = w; } public void setHeight (double h) {height = h;} public double area ( ) { return (width * height);} }

Page 38: Chapter 2

LSP Example (contd.)

Assume we need a Square class. Clearly a square is a rectangle, so the Square class should be derived from the Rectangle class.

Observations: A square does not need both a width and a height as attributes, but it will

inherit them from Rectangle anyway. So each Square object wastes a little memory -- but this is not a major concern.

The inherited setWidth ( ) and setHeight ( ) methods are not really appropriate for a Square, since the width and height of a square are identical. So we’ll need to override the methods setWidth ( ) and setHeight ( ).

Page 39: Chapter 2

LSP Example (contd.)

Here’s the Square class: // A Square class public class Square extends Rectangle { public Square (double s) { super (s, s);} public void setWidth (double w) { super.setWidth (w); super.setHeight(w); } public void setHeight (double h) { super.setWidth (h); super.setHeight (h); }}

setWidth ( ) and setHeight ( ) overridden to reflect Square semantics

Page 40: Chapter 2

LSP Example (contd.)

Everything looks good. But consider this function! public class TestRectangle { // Define a method that takes a Rectangle reference. public static void testLSP (Rectangle r) { r.setWidth (4.0); r.setHeight (5.0); System.out.println (“Width is 4.0 and Height is 5.0” + “, Area” +

r.area () ); if (r.area ( ) == 20.0 ){ System.out.println (“Looking good \n”); else System.out.println(“Huh?? What kind of rectangle is this?? \n”); }

Page 41: Chapter 2

LSP Example (Contd.)

public static void main (String args[] ) { // Create a Rectangle and a Square Rectangle r = new Rectangle (1.0, 1.0); Square s = new Square (1.0);

// Now call the testLSP method. According to LSP it should work for either

// Rectangles or Squares. Does it? testLSP ( r ); testLSP (s); }}

Page 42: Chapter 2

LSP Example (contd.)

Test program output: Width is 4.0 and Height is 5.0, so Area os 20.0 Looking good!

Width is 4.0 and Height is 5.0, so Area is 25.0 Huh?? What kind of rectangle is this??

Looks like we violated LSP!

Page 43: Chapter 2

The Problem? The programmer of the testLSP ( ) method made the reasonable assumption

that changing the width of a Rectangle leaves its height unchanged.

Passing a Square object to such a method results in problems, exposing a violation of LSP.

The Square and Rectangle classes look self consistent and valid. Yet a programmer, making reasonable assumptions about the base class, can write a method that causes the design model to break down.

Solutions cannot be viewed in isolation, they must also be viewed in terms of reasonable assumptions that might be made by the users of the design.

Page 44: Chapter 2

The Problem (contd.) A mathematical square might be a rectangle, but a Square

object is a not a Rectangle object, because the behavior of a Square object is not consistent with the behavior of a Rectangle object!

Behaviorally, a Square is not a Rectangle! A Square object is hence not polymorphic with a Rectangle object.

Hint on LSP violation: when simple methods such as the setWidth and setHeight have to be overridden, inheritance needs to be re-examined!

Page 45: Chapter 2

LSP is about Semantics and Replacement

The meaning and purpose of every method and class must be clearly documented– Lack of user understanding will induce de facto ( 事實的 ) violations of

LSP

Replaceability is crucial– Whenever any class is referenced by any code in any system,

any future or existing subclasses of that class must be 100% replaceable– Because, sooner or later, someone will substitute a subclass;

• it’s almost inevitable.

Page 46: Chapter 2

LSP and Replaceability Any code which can legally call another class’s methods

– must be able to substitute any subclass of that class without modification:

Client Service Class

Client

Service Class

Unexpected Subclass

Page 47: Chapter 2

Alternative Solution:

Favor Composition over Inheritance

Page 48: Chapter 2

Composition Method of reuse in which new functionality is obtained by

creating an object composed of other objects The new functionality is obtained by delegating functionality to

one of the objects being composed. Sometimes also called Delegation, Aggregation or Containment

(although some associate different meanings to these) Aggregation - when one object owns or is responsible for another object

and both objects have identical lifetimes (GoF) Aggregation - when one object has a collection of objects that can exist on

their own (UML) Containment - a special kind of composition in which the contained object

is hidden from other objects and access to the contained object is only via the container object (Coad)

Delegation - when one object delegates the execution of a behavior to another object (Bruegge)

Page 49: Chapter 2

Composition

Composition can be – By reference – By value

C++ allows composition by value or by reference Java allows only by reference

Page 50: Chapter 2

Pros and Cons of Composition Advantages

– Contained objects are accessed by the containing class solely through their interfaces

– “Black-box” reuse - internal details of contained objects are not visible

– Good encapsulation– Fewer implementation dependencies– Each class is focused on just one task– Can be defined dynamically at run-time

Disadvantages– Resulting systems often tend to have more objects– Interfaces must be defined carefully in order to use many different

objects as composition blocks

Page 51: Chapter 2

Inheritance

Method of reuse in which new functionality is obtained by extending the implementation of an existing object

The generalization class (superclass) explicitly captures the common attributes and methods

The specialization class (the subclass) extends the implementation with additional attributes and methods

Page 52: Chapter 2

Advantages and Disadvantages of Inheritance Advantages

– New implementation is easy, since most of it is inherited

– Easy to modify or extend the implementation being reused

Disadvantages– Breaks encapsulation, since it exposes a subclass to implementation details

of its superclass

– “White-box” reuse, since internal details of superclass are visible to subclasses

– Subclasses may have to change if the implementation of the superclass changes

– Implementation inherited from superclasses cannot be changed at runtime

Page 53: Chapter 2

Inheritance vs Composition Example

[Adapted from Bruegge] Needed: variant of HashSet that keeps track of the

number of attempted insertions. Solution: subclass HashSet public class NewHashSet extends HashSet {

private int addCount = 0; public NewHashSet (Collection c) { super ( c); } public NewHashSet (int initCap, float loadFactor) { super (initCap, loadFactor); }

Page 54: Chapter 2

Example (contd.)

public boolean add (Object o) { addCount++; return super.add (o); } public boolean addAll (Collection c) { addCount += c.size (); return super.addAll ( c ); } public int getAddCount ( ) { return addCount; }}

Modifications to the HashSet

Page 55: Chapter 2

Example (contd.) Looks good! Or not??? Test:

public static void main (String[] args) {

NewHashSet s = new NewHashSet ( ); s.addAll (Arrays.asList(new String[] {“Snap”, “Crackle”,

“Pop”})); System.out.println(s.getAddCount () ); }

• We get a result of 6, not the expected 3. Why?

• Its because the internal implementation of addAll () in the HashSet superclass itself invokes the add ( ) method.

Page 56: Chapter 2

Inheritance vs Composition

Several ways to fix this -- but note the fragility of the design -- Implementation of the superclass effects the operation of the subclass.

Best fix - use composition– Write a NewSet class that is composed of a Set object. The

NewSet will duplicate the Set interface, but all Set operations will be “forwarded” to the contained Set object

– NewSet is known as a wrapper class - “wraps” an instance of the Set object

– “Delegation through composition” or simply “Delegation”

Page 57: Chapter 2

Example -- Take 2 public class NewSet implements Set { private final Set s; private int addCount = 0; public NewSet (Set s) { this.s = s; } public boolean add (Object o) { addCount++; return s.add(o); } public boolean addAll (Collection c) { addCount += c.size; return s.addAll ( c) ; } public int getAddCount ( ) {return addCount;} //forwarding methods (rest of the Set Interface methods)}

Page 58: Chapter 2

Things to Note

Several things to note:– This class is a Set– It has one constructor whose argument is a Set– The contained Set object can be an object of any class that

implements the Set interface, not just a HashSet– Very flexible -- can wrap any preexisting Set object

Example: List list = new ArrayList ( ); Set s1 = new NewSet (new TreeSet (list)); int capacity = 7; float loadFactor = .66f; Set s2 = new NewSet (new HashSet (capacity, loadFactor));

Page 59: Chapter 2

Some Rules

Use inheritance only when all of the following criteria are satisfied:– A subclass expresses “is a special kind of” and not “is a role

played by a”– An instance of a subclass never needs to become an object of

another class– A subclass extends, rather overrides or nullifies, the

responsibilities of the superclass– A subclass does not extend the capabilities of what is merely a

utility class– Within the problem domain, specializes a role, transaction or

device

Page 60: Chapter 2

The Liskov Substitution Principle The Liskov Substitution Principle (LSP) makes it clear that the

ISA relationship is all about behavior In order for the LSP to hold (and with it the Open-Closed

Principle) all subclasses must conform to behavior that the clients expect of the base classes they use.

A subtype must have no more constraints than its base type, since the subtype must be usable anywhere the base type is usable

If the subtype has more constraints than its base type, there would be uses that would be valid for the base type, but that would violate one of the extra constraints of the subtype and thus violate the LSP!

The guarantee of the LSP is that a subclass can always be used wherever its base class is used!

Page 61: Chapter 2

Principle# 3

The Dependency Inversion Principle

Page 62: Chapter 2

The Dependency Inversion Principle

I. High-level modules should not depend on low-level modules.

Both should depend on abstractions.

II. Abstractions should not depend on details.

Details should depend on abstractionsR. Martin, 1996

OCP states the goal; DIP states the mechanism

A base class in an inheritance hierarchy should not know any of its subclasses

Modules with detailed implementations are not depended upon, but depend themselves upon abstractions

Page 63: Chapter 2

Why “Inversion” ?

Traditional functional programming:– High level modules: business/application rules

– Low level modules: implementation of the business rules

– High level modules complete their functionality by calling/invoking the low level implementation provided by the low level modules

• High level depends on the lower level

Policy layer

Mechanism layer

Utility layer

Page 64: Chapter 2

What are the Implications?

1. Dependency is transitive: Changes in the lower level modules can have direct effects on the higher level modules, forcing them to change in turn.• Absurd! High level modules should be driving change not the other way

round.2. Reuse: We should be able to reuse the high level, policy setting modules

• (pretty good already at reusing the lower level implementations -- libraries)

• Difficult to reuse higher level modules when they depend on lower level details

3. Conclusions:– Strive for having higher level modules be independent of the lower level

modules– Principle is at the heart of framework design!

Page 65: Chapter 2

Inversion of Ownership

Each high level module declares an abstract interface for the services it needs

Lower level layers are realized using through the abstract interface

Here:– Upper level layers do not depend on the lower level modules

– Lower layers depend on the abstract service layers declared in the upper layers!

Page 66: Chapter 2

Procedural vs. OO Architecture

Procedural Architecture

Object-Oriented Architecture

Page 67: Chapter 2

Better “inverted” Design Design applies DIP (1).Inversion of Ownership!

The client “owns” the interface Their “services” derive from the: the utility libraries don’t own the interfaces they implement.

Sometimes called the Hollywood principle: “Don’t call us, we’ll call you!”Advantages:

Policy Layer is now unaffected by changes in the Utility LayerPolicy Layer is now reusable!Inverting Dependencies breaks:

Transitive dependencyDirect dependency in most cases

Provides design that is more flexible, durable and mobile!

Policy

Policy Layer<< interface >>Policy Service Interface

Mechanism

MechanismLayer

<< interface >> Mechanism Service Interface

Utility

UtilityLayer

Page 68: Chapter 2

Why Inversion?

HighLevel

AbstractInterface1<<Interface>>

AbstractInterface2<<Interface>>

AbstractInterface3<<Interface>>

DetailImpl1 DetailImpl2 DetailImpl3

Page 69: Chapter 2

Depend on Abstractions (1/2)

Naïve but powerful principle– Should not depend on concrete classes– All relationships in a program must terminate at an abstract class or

interface According to this heuristic:

– No variable should hold a pointer or reference to a concrete class– No class should derive from a concrete class– No method should override an implemented method of any of its base

classes This heuristic is violated at least once in every program

– Classic example: use of String class– If a concrete class is non-volatile, ignore this heuristic

Page 70: Chapter 2

Depend on Abstractions (2/2)

Most classes “we” write for our programs are volatile -- principle should be applied here.

Not a complete solution -- – Interface of volatile class may change, – May cause propagation of change to abstract interface

it implements– Naïve!

Page 71: Chapter 2

DIP Related Heuristic

Use inheritance to avoid direct bindings to classes:

Design to an interface, not an implementation!

Client

Interface(abstract class)

Implementation(concrete class)

Page 72: Chapter 2

Design to an Interface

Abstract classes/interfaces:– tend to change much less frequently

– abstractions are ‘hinge points’ where it is easier to extend/modify

– shouldn’t have to modify classes/interfaces that represent the abstraction (OCP)

Exceptions– Some classes are very unlikely to change;

• therefore little benefit to inserting abstraction layer

• Example: String class

– In cases like this can use concrete class directly• as in Java or C++

Page 73: Chapter 2

DIP Related Heuristic

Avoid structures in which higher-level layers depend on lower-level abstractions:– In example below, Policy layer is ultimately dependant on Utility layer.

Avoid Transitive Dependencies

Policy Layer

MechanismLayer

UtilityLayer

Depends on Depends on

Page 74: Chapter 2

Solution to Transitive Dependencies

Use inheritance and abstract ancestor classes to effectively eliminate transitive dependencies:

Policy Layer

MechanismLayer

UtilityLayer

depends on

depends on UtilityInterface

MechanismInterface

Page 75: Chapter 2

DIP - Related Heuristic

If you cannot find a satisfactory solution for the class you are designing, try delegating responsibility to one or more classes:

When in doubt, add a level of indirection

Problem Holder

ProblemSolver

Page 76: Chapter 2

When in doubt ... It is generally easier to remove or by-pass existing

levels of indirection than it is to add them later:

XSo, Blue class re-implements some or all of green class’s responsibilities for efficiency and calls red object directly

Blue class’s indirect message calls to red class fail to meet some criteria (e.g. real-time constraints, etc.)

Page 77: Chapter 2

DIP Example Dependency Inversion Principle can be applied whenever one class

sends a message to another. Consider the case of a Button and Lamp object.

– Button:• senses the external environment• receives poll message• Determines whether or not user has “pressed” it.

– Lamp:• Affects the external environment• On receiving turnOn message, illuminates the light• On receiving turnOff message, extingishes the light.

Actual physical mechanism for the Lamp and the Button is irrelevant.

Page 78: Chapter 2

Naïve Design

public class Button { private Lamp itsLamp; public Button (Lamp l) { itsLamp = l;}

public void poll ( ){ if (/* some condition*/) itsLamp.turnOn ( ); else itsLamp.turnOff ( ); }

}

public class Lamp { public void turnOn ( ); public void turnOff ( ); }

Button Lamp

+ poll ( ) + turnOn ( )+ turnOff ()

Why is this a naïve design?

Page 79: Chapter 2

Why is the design naïve?

The dependency between Lamp and Button implies that Lamp cannot be modified without changing (at least recompiling) the

Also - not possible to reuse the Button class to control a Motor/Portal object.

The Button and Lamp code violates the DIP.

Page 80: Chapter 2

Applying DIP (a)

Button

Lamp

+ poll ( )

<< interface >>Button Server

+ turnOn ( )+ turnOff ()

Page 81: Chapter 2

Adding More Abstraction

If there can be multiple types of buttons or switching devices, abstraction can used to further refine the design!

Button(Abstract)

ButtonClient(Abstract)

Button (Implementation)

Lamp

Page 82: Chapter 2

DIP-Conforming Code public abstract class ButtonClient { public abstract void turnOn ( ); public abstract void turnOff ( ); };

public abstract class Button { protected ButtonClient bc; Button (ButtonClient b) { bc = b; } public abstract boolean getState ( ); public void detect ( ) { boolean buttonOn = getState ( ); if (buttonOn) bc.turnOn ( ); else bc.turnOff ( ); } }

public class Lamp extends ButtonClient { public void turnOn ( ) { //code } public void turnOff ( ) { // code} }

public class ButtonImplementation extends Button {

ButtonImplementation (ButtonClient b)

{ super(b); } public boolean getState ( ) { // code} }

Page 83: Chapter 2

The Dependency Inversion Principle One motivation behind the DIP is to prevent you from depending upon

volatile modules.– Typically, concrete classes/methods change frequently, while abstract

classes/methods change are more stable. Abstractions are “hinge points” -- they represent the places where the

design can bend or be extended, without the abstractions themselves being modified (OCP)

One of the most common places that designs depend upon concrete classes is when those designs create instances. By definition, you cannot create instances of abstract classes. Thus to create instances you must depend on concrete classes!– An elegant solution to this problem - Abstract Factory Pattern

Corollary: if a class/modules are concrete but extremely stable this principle can be relaxed.

Page 84: Chapter 2

The Founding Principles

The three principles are closely related

Violating either LSP or DIP invariably results in violating OCP– LSP violations are latent violations of OCP

It is important to keep in mind these principles to get most out of OO development...

Page 85: Chapter 2

Design Patterns

Page 86: Chapter 2

Patterns of Learning

Successful solutions to many areas of human endeavor are deeply rooted in patterns– In fact, an important goal of education is

transmitting patterns of learning from generation to generation

Learning to develop good software is similar to learning to play good chess!

Page 87: Chapter 2

Becoming a Chess Master First learn the rules

– e.g., names of pieces, legal movements, chess board geometry and orientation etc.

Then learn the principles– e.g., relative value of certain pieces, strategic value of

center squares, power of a threat etc. However, to become a master of chess, one must

study the games of other masters– These games contain patterns that must be understood,

memorized and applied repeatedly There are hundred of these patterns

Page 88: Chapter 2

Becoming a Software Design Master First learn the rules

– e.g., the algorithms, data structures and languages of software Then learn the principles

– e.g., structured programming, modular programming, object-oriented programming, generic programming, principles of OO etc.

However, to become a master of software design, one must study the designs of other masters– These designs contain patterns that must be understood,

memorized and applied repeatedly There are hundred of these patterns

Page 89: Chapter 2

What is a Pattern ?

Each pattern describes a problem

which occurs over and over again in our environment,

and then describes

the core of the solution to that problem,

in such a way that

you can use this solution a million times over,

without ever doing it the same way twice

C. Alexander, “The Timeless Way of Building”, 1979

Page 90: Chapter 2

Why Use Patterns ?

An additional layer of abstraction– separate things that change from things that stay the same– distilling out common factors between a family of similar problems– similar to design

Insightful and clever way to solve a particular class of problems– most general and flexible solution

Patterns help you learn from other’s successes, instead of your own failures

Mark Johnson (cited by B. Eckel)

Page 91: Chapter 2

Design Patterns Design patterns represent solutions to problems that arise

when developing software within a particular context– Patterns = Problem/Solution pair in Context

Capture static and dynamic structure and collaboration among key participants in software designs– key participant – major abstraction that occur in a design problem– useful for articulating the how and why to solve non-functional forces.

Facilitate reuse of successful software architectures and design– i.e. the “design of masters”… ;)

Page 92: Chapter 2

Gang of Four (GoF)

Erich Gamma, Richard HelmRalph Johnson & John Vlissides

Design Patterns – Elements ofReusable Object-Oriented Software

Addison-Wesley, 1995.(As CD, 1998)

First systematic software pattern description.

Page 93: Chapter 2

Design Pattern Catalog - GoF

Purpose

Creational Structural Behavioral

Class Factory Method Adapter Interperter

ScopeObject

AbstractFactory

Builder Prototype Singleton

Adapter Bridge Composite Decorator Facade Flyweight Proxy

Chain of Responsibility Command Iterator Mediator Momento Observer State Strategy Vistor

Page 94: Chapter 2

Benefits of Design Patterns Inspiration

– patterns don't provide solutions, they inspire solutions– Patterns explicitly capture expert knowledge and design tradeoffs and

make this expertise widely available– ease the transition to object-oriented technology

Patterns improve developer communication– pattern names form a vocabulary

Help document the architecture of a system– enhance understanding

Design patterns enable large-scale reuse of software architectures

Page 95: Chapter 2

The Strategy Pattern

Page 96: Chapter 2

Long time ago….

It started with a simple SimUDuck app– Simulation can show a large variety of duck species

swimming and making quacking sounds.

Duck quack( ) swim ( ) display ( ) // Other duck like methods

MallardDuckdisplay ( ) { // looks like a mallard }

RedHeadDuckdisplay ( ) { // looks like a redhead}

All ducks quack () and swim (), the superclass takes care of the implementation code.

Each duck subype is responsible for implementing its own display () behavior for how it looks on the screen.

The display ( ) method is abstract, since all duck types look different.

Lots of other types of ducks inherit from the Duck class.

Page 97: Chapter 2

But now we need the ducks to fly…

No problem!

Duck quack( ) swim ( ) display ( ) fly ( ) // Other duck like methods

MallardDuckdisplay ( ) { // looks like a mallard }

RedHeadDuckdisplay ( ) { // looks like a redhead}

All subclasses inherit fly ( )

Page 98: Chapter 2

But something went horribly wrong..

At a demo the program failed to impress anyone -- there were rubber ducks flying across the screen!

What happened? – A localized update to the code caused a non-local side effect (flying rubber

ducks)

Duck quack( ) swim ( ) display ( ) fly ( ) // Other duck like methods

MallardDuckdisplay ( ) { // looks like a mallard }

RedHeadDuckdisplay ( ) { // looks like a redhead}

By putting the fly ( ) in the superclass, ALL ducks got the ability to fly including those that shouldn’t!

RubberDuck quack () { // overridden to Squeak }display ( ) { // looks like a rubberduck }

Page 99: Chapter 2

A Solution

Can override the fly ( ) method similar to the quack ( ) method. fly ( ) {

Do nothing}

What would happen if we added a DecoyDuck to the class hierarchy? It doesn’t quack ( ) or fly ( ).

What else could you try?

Page 100: Chapter 2

How about an interface?

Need a cleaner way to make some (but not all) ducks fly or quack.– Could take the fly ( ) out of the superclass and make an Flyable interface

with a fly ( ) method, and maybe a Quackable interface as well.

Duck swim ( ) display ( )// Other duck like methods

MallardDuckdisplay ( ) { // looks like a mallard }

RedHeadDuckdisplay ( ) { // looks like a redhead}

RubberDuck quack () { // overridden to Squeak }display ( ) { // looks like a redhead}

<<interface>>

Flyable

fly ( )

<<interface>>

Quackable

quack ( )

What do you think about this design?

Page 101: Chapter 2

What do you think?

Dumb!!!! “Duplicate code” all over the place. A small change to the flying

behavior will require changing all 48 of the Duck subclasses!

And what is the one thing that you can count on it software development?

CHANGE!Separate what varies - separate what changes from what stays

constant.

1. We know that fly ( ) and quack ( ) are the parts of the Duck class that vary across ducks.

2. To separate these behaviors from the Duck class, we’ll pull both methods out of the Duck class and create a new set of classes to represent each behavior.

Page 102: Chapter 2

Separating what varies

The Duck class is still the superclass of all ducks, but we are pulling out the fly( ) and quack ( ) behaviors and putting them into another class structure.

Now flying and quacking each get their own set of classes.

Various behavior implementations are going to live here.

Duck Behaviors

Pull out what varies

Duck behaviors will now live in a separate class -- a class that implements a particular behavior interface.That way duck classes won’t need to know any of the implementation details of their own behaviors. But how???

Page 103: Chapter 2

DP: Program to an Interface, not an Implementation

<<interface>> FlyBehavior

fly ( )

FlyWithWings

fly ( ) { // implements duck flying }

FlyNoWay

fly ( ) { // do nothing - can’t fly }

Here we have an interface that all flying classes implement. All new flying classes just need to implement the fly method.

Here’s the implementation of flying for all ducks with wings.

Implementation for all ducks that can’t fly.

We can have a similar implementation hierarchy for the Quackable behavior.

We can now also add new behaviors without modifying any of our existing classes or touching any of the Duck classes that use flying behavior. --- We get REUSE without all the baggage of inheritance.

Page 104: Chapter 2

Integrating Duck Behavior

Key is delegation - we now delegate the quacking and flying behaviors to methods defined in other classes - QuackBehavior and FlyingBehavior

Duck

FlyBehavior flyBehavior

QuackBehavior quackBehavior

performQuack ( )

swim ( )

display ( )

performFly ( )

// other duck-like methods

The behavior variables are declared as the behavior INTERFACE type.

These replace the fly ( ) and quack ( ) methods.

Instance variables hold a reference to a specific behavior at runtime.

public class Duck { QuackBehavior quackBehavior; // other stuff

public void performQuack ( ){ quackBehavior.quack ( ); }}

Delegation

Page 105: Chapter 2

Putting it together…. public class MallardDuck extends Duck { public MallardDuck ( ) { quackBehavior = new Quack ( ); flyBehavior = new FlyWithWings ( ); } } public class Quack implements QuackBehavior { public void quack ( ){ System.out.println (“Quack”); } }

public class FlyWithNoWings impelments FlyBehavior { public void fly ( ){ System.out.println (“I can’t fly” ); }} public class MiniDuckSimulator { public static void main (String[] args) { Duck mallard = new MallardDuck ( ); mallard.performQuack ( ); mallard.performFly ( ); }}

With your knowledge of factories, these would probably not be hardcoded!

Page 106: Chapter 2

Setting Behavior Dynamically! public void setFlyBehavior (FlyBehavior fb) { flyBehavior = fb; } public void setQuackBehavior (QuackBehavior qb) { quackBehavior = qb; }

public class ModelDuck extends Duck { public class ModelDuck { flyBehavior = new FlyNoWay () ;

quackBehavior = new Quack ( ); } public void display ( ) { System.out.println(“I’m a model duck”); }}

public class FlyRocketPowered implements FlyBehavior { public void fly ( ) { System.out.println(“I’m flying with a rocket”); } }

// test it out in main Duck model = new ModelDuck ( ); model.performFly ( ); model.setFlyBehavior (new FlyRocketPowered ( )); model.performFly ( );

Adding a couple of new methods to the Duck class

Create a new type of Duck

Make a new FlyBehavior type

What do you think happens? -- Changing the Duck’s behavior at runtime!

Page 107: Chapter 2

The Strategy Design PatternThe Strategy Design Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithms vary independently from the clients that use it.

Strategy AlgorithmInterface ( )

Context ContextInterface ( )

ConcreteStrategyA AlgorithmInterface ( )

ConcreteStrategyB AlgorithmInterface ( )

ConcreteStrategyC AlgorithmInterface ( )

Context manages the data structures that a concrete strategy operates on.

ConcreteStrategy classes provide the implementations of the different strategies. These operate on the data structures in the the Context, and can be set dynamically.

Defines the generic interface

Page 108: Chapter 2

Summary

Strategy pattern allows selection of one of several algorithms dynamically.

Algorithms may be related via an inheritance hierarchy or unrelated [must implement the same interface]

Strategies don’t hide everything -- client code is typically aware that there are a number of strategies and has some criteria to choose among them -- shifts the algorithm decision to the client.

Page 109: Chapter 2

Observer Pattern

Keeping your Objects in the Know!

Page 110: Chapter 2

The Weather-O-Rama!

Humidity Sensor Device

Temperature Sensor Device

Pressure Sensor Device

Weather Station

Pulls data Displays

Current conditions is one of three different displays. The user can also get weather stats and a forecast.

Display Device

Current Conditions

Temp: 72Humidity: 60Pressure:

Weather-O-Rama provides

What we implement

The Job: Create an app that uses the WeatherData object to update three displays for current conditions, weather stats, and a forecast.

Page 111: Chapter 2

The WeatherData class

WeatherData

getTemperature ( ) getHumidity ( ) getPressure ( ) measurementChanged ( )

// other methods

These three methods return the most recent weather measurements for temperature, humidity, and pressure respectively.

We don’t care HOW these variables are set; the WeatherData object knows how to get updated information from the Weather Station

/* * This method gets called whenever the * measurements have been updated. * / public void measurementsChanged ( ){ // Your code goes here }

A clue: what we need to add!

Page 112: Chapter 2

The Specs so far The WeatherData class has getter methods for three

measurement values: temperature, humidity, and pressure.

The measurementsChanged ( ) method is called anytime new weather measurement data is available. (We don’t know or care how this method is called; we just know that it is)

We need to implement three display elements that use the weather data: a current conditions display, a statistics display, and a forecast display. These displays must be updated each time WeatherData has new measurements.

The system must be expandable -- other developers can create new custom display elements and users can add or remove as many display elements as they want to the application.

Page 113: Chapter 2

A First Misguided Attempt at the Weather Station

public class WeatherData {// instance variable declarationspublic void measurementsChanged ( ) { float temp = getTemperature ( ); float humidity = getHumidity ( );

float pressure = getPressure ( );

currentConditionsDisplay.update (temp, humidity, pressure); statisticsDisplay.update (temp, humidity, pressure); forecastDisplay.update (temp, humidity, pressure); } // other WeatherData methods here}

Grab the most recent measurements by calling the WeatherData’s getter methods (already implemented)

Now update the displays.

Call each display element to update its display, passing it the most recent measurements.

Page 114: Chapter 2

What’s wrong with the first implementation?

public class WeatherData {// instance variable declarationspublic void measurementsChanged ( ) { float temp = getTemperature ( ); float humidity = getHumidity ( );

float pressure = getPressure ( );

currentConditionsDisplay.update (temp, humidity, pressure); statisticsDisplay.update (temp, humidity, pressure); forecastDisplay.update (temp, humidity, pressure); } // other WeatherData methods here}

Area of change, we need to encapsulate this.

At least we seem to be using a common interface to talk to the display elements…they all have an update ( ) method that takes temp, humidity and pressure values.

By coding to concrete implementations we have no way to add or remove other display elements without making changes to the program.

Page 115: Chapter 2

Time for the Observer!

The Newspaper or Magazine subscription model:– A newspaper publisher goes into business and begins

publishing newspapers

– You subscribe to a particular newspaper, and every time there is a new edition, its gets delivered to you. As long as you remain a subscriber, you get new newspapers.

– You unsubscribe when you don’t want the newspapers anymore -- and they stop being delivered

– While the publisher remains in business people, hotels, airlines etc constantly subscribe and unsubscribe to the newspaper.

Page 116: Chapter 2

Publishers + Subscribers = Observer Pattern

Publisher == Subject Subscribers == Observers

int

2

Observer Objects

The observers have subscribed to the Subject to receive updates when the subject’s data changes.

When data in the Subject changes, the observers are notified.

2

2

2

New data values are communicated to the observers in some form when they change.

This object isn’t an observer so it doesn’t get notified when the subject’s data changes.

Subject object manages some data.

Page 117: Chapter 2

The Observer Pattern DefinedThe Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

int

2

Observer Objects

2

2

2

One to many relationship (Subject can have many observers)

Object that holds state

Dependent objects(observers are dependent on the subject to update them when data changes.) Automatic update/notification

Page 118: Chapter 2

Observer Class DiagramHere’s the Subject interface. Objects use this interface to register as observers and also to remove themselves from being observers.

Each subject can have many observers

All potential observers need to implement the Observer interface. This interface has just one method, update ( ), that gets called when the Subject’s state changes.

Concrete observers can be any class that implements the Observer interface. Each observer registers with a concrete subject to receive updates.

The concrete subject may also have methods for setting and getting its state.

A concrete subject always implements the Subject interface. In addition to the register (attach) and remove (detach) methods, the concrete subject implements a notify() method to notify observers whenever state changes.

Page 119: Chapter 2

ForecastDisplay

update ( ) display ( ) { // display the forecast }

Designing the Weather Station

<<interface>> Subject

registerObservers ( ) removeObservers ( ) notifyObservers ( )

<<interface>> Observer

update ( )

observers

WeatherData

registerObservers ( ) removeObservers ( ) notifyObservers ( )

getTemperature ( ) getHumidity ( ) getPressure ( ) measurementsChanged ( )

CurrentConditions

update ( ) display ( ) { // display current measurements }

StatisticsDisplay

update ( ) display ( ) { // display avg, min, and max measurements }

<<interface>> DisplayElement

display ( )

Subject interfaceAll weather components implement the Observer interface. This gives the subject a common interface to talk to when it comes time to update.

Create an interface for all display elements to implement. The display elements just need to implement a display ( ) method.

WeatherData now implements the Subject interface.

Page 120: Chapter 2

Implementing the Weather Station public interface Subject { public void registerObserver (Observer o); public void removeObserver (Observer o); public void notifyObservers ( );}

public interface Observer { public void update (float temp, float humidity, float pressure); }

public interface DisplayElement { public void display ( ); }

Both of these methods take an Observer as an argument, that is the Observer to be registered or removed.

This method is called to notify all observers when the Subject’s state has changed.

The Observer interface is implemented by all observers, so they all have to implement the update ( ) method.

These are the state values the Observers get from the Subject when a weather measurement changes.

The DisplayElement interface just includes one method, display ( ), that we will call when the display element needs to be displayed.

Page 121: Chapter 2

Implementing the Subject Interface in WeatherData public class WeatherData implements Subject { private ArrayList observers;

private float temperature;private float humidity;private float pressure;

public WeatherData ( ){ observers = new ArrayList ( );

} public void registerObserver (Observer o) {

observers.add(o);}

public void removeObserver (Observer o) { int j = observer.indexOf(o); if (j >= 0) { observers.remove(j); } }public void notifyObservers ( ) { for (int j = 0; j < observers.size(); j++) {

Observer observer = (Observer)observers.get(j);observer.update(temperature, humidity, pressure);

}}public void measurementsChanged ( ) { notifyObservers ( ); }// add a set method for testing + other methods.

}

Added an ArrayList to hold the Observers, and we create it in the constructor

Notify the observers when measurements change.

Here we implement the Subject Interface

Page 122: Chapter 2

The Display Elements public class CurrentConditionsDisplay implements Observer, DisplayElement {

private float temperatue;private float humidity;private Subject weatherData;

public CurrentConditionsDisplay (Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver (this);}public void update (float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity;

display ( );}public void display ( ){ System.out.println(“ Current conditions : “ + temperature + “ F degrees and “ + humidity + “ % humidity” );}

}

Implements the Observer and DisplayElement interfaces

The constructors passed the weatherData object (the subject) and we use it to register the display as an observer.

When update ( ) is called, we save the temp and humidity and call display ( )

The display ( ) method just prints out the most recent temp and humidity.

Page 123: Chapter 2

Using Java’s Built-in Observer Pattern Java has built-in support in several of its APIs for the Observer pattern Most general: Observer interface and the Observable class in the

java.util package.– Observer == Observer– Observable == Subject

Observable

addObserver ( ) deleteObserver ( ) notifyObservers ( ) setChanged ( )

WeatherData

getTemperature ( ) getHumidity ( ) getPressure ( )

<<interface>> Observer update ( )

GeneralDisplay update ( ) display ( )

StatisticsDisplay update ( ) display ( )

ForecastDisplay update ( ) display ( )

The Observable class keeps track of all your observers and notifies them for you.

Should be familiar -- same as before!

Some changes to the update ( ) method but basically the same.

Observable is a CLASS not an interface, so WeatherData extends it!

This doesn’t look familiar -- we will see it shortly.

WeatherData does not need to implement register, remove and notify -- it inherits them

Page 124: Chapter 2

Using Java’s Built-in Observer Pattern For an Object to become an Observer:

– Implement the Observer interface (this time the java.util.Observer interface) and call addObserver ( ) on any Observable object. To remove use deleteObserver ( ) method.

For the Observable to send notifications– Become an Observable by extending java.util.Observable

superclass– Then a 2 step process:

1. First call the setChanged ( ) method to signify that the state has changed in your object.

2. Then call one of two notifyObservers ( ) methods– notifyObservers ( ) or notifyObservers (Object arg)

For the Observer to receive notifications– Implement the update ( ) method as before. Signature a bit different.– update (Observable o, Object arg)

This takes an arbitrary data object that gets passed to each Observer when it is notified.

Subject that send the notification.

Page 125: Chapter 2

The setChanged ( ) Method The setChanged ( ) method is used to signify that the state has changed and that

notifyObservers (), when it is called, should update its observers.– If notifyObservers( ) is called without first calling the setChanged ( ), the observers

will NOT be notified. Pseudocode: setChanged ( ){

changed = true;}notifyObservers ( Object arg ){ if (changed ) { for every observer on the list {

call update(this, arg);

} changed = false; } } notifyObservers ( ) { notifyObservers (null); }

The setChanged() method sets the changed flag to true

notifyObserver ( ) only notifies its observers if the changed flag is true.

And after it notifies the observers it sets the changed flag back to false.

Page 126: Chapter 2

Why is the setChanged ( ) necessary? setChanged ( ) method is there to give you more

flexibility– Optimize the notifications

– Example: • if the sensors are sensitive readings may fluctuate by a few tenths of

the a degree.

• May not want to update the observers with every fluctuation

• setChanged ( ) allows you to control the notification points.

Other relevant methods in Observable:– clearChanged ( )

– hasChanged ( )

Page 127: Chapter 2

The notify ( ) -- Push and Pull Methods public void measurementsChanged ( ) {

setChanged ( );notifyObservers ( );

}

public void measurementsChanged ( ){setChanged ( );notifyObservers (this);

}

We first call the setChanged ( ) to indicate that the state has changed.

We aren’t sending a data object with the notifyObservers ( ) call. The Observers are aware of the subject and they will use that to “pull” the latest information from the subject.

A “push” method -- the modified data is being pushed to the observers.

Page 128: Chapter 2

The Dark Side of the java.util.Observable Doesn’t the java.util.Observable violate OO design principle

of programming to interfaces and not implementations?

Yes it does! Observable is a class and not an interface. Moreover it does not even implement an interface.

java.util.Observable has a number of problems that limit its usefulness and reuse

1) Observable is a class: you have to subclass it => you can’t add on the Observable behavior to an existing class that already extends another superclass. This limits its potential reuse.

2) There isn’t an Observable interface so you cannot provide your own implementation or swap out the Observable implementation with say a multithreaded implementation

3) Observable protects crucial methods: setChanged () is protected. It means that you cannot call setChanged unless you have subclassed Observable. Violates : favor composition over inheritance!

Page 129: Chapter 2

Other places to find Observer Pattern in Java Both JavaBeans and Swing also provide

implementations of the Observer pattern Look under the hood of JButton’s super class

AbstractButton– Has many add/remove listener methods: allow you to add and

remove observers (called listeners in Swing)– These “listeners” are available for various types of events that

occur on the Swing component– Example: ActionListener lets you “listen in” on any types

of actions that might occur on a button -- like a button press. Also check out the PropertyChangeListener in

JavaBeans

Page 130: Chapter 2

Summary OO Principle in play: Strive for loosely coupled designs between objects that

interact. Main points:

– The Observer pattern defines a one to many relationship between objects– Subjects (observables), update Observers using a common interface– Observers are loosely coupled in that the Observable knows nothing about them,

other than they implement the Observer interface.– You can push or pull data from the Observable when using the pattern (“pull” is

considered more correct)– Don’t depend on a specific order of notification for your Observers– Java has several implementations of the Observer Pattern including the general

purpose java.util.Observable– Watch out for issues with java.util.Observable– Don’t be afraid to create our own version of the Observable if needed– Swing makes heavy use of the Observer pattern, as do many GUI frameworks– You find this pattern in other places as well including JavaBeans and RMI.

Page 131: Chapter 2

The Decorator Pattern

“Decorating Objects -- Power of Extension at Runtime”

Page 132: Chapter 2

Welcome to Starbuzz Coffee! Brief Intro: Starbuzz Coffee has made a name for itself as the fastest growing

coffee shop. Because they have grown so quickly, they are scrambling to update their ordering system to match their beverage offerings….

Beverage description getDescription ( ) cost ( ) // other useful methods

HouseBlend cost ()

DarkRoast cost ()

Decaf cost ()

Expresso cost ()

Beverage is an abstract class, subclassed by all beverages offered in the coffee shop.

The description instance variable is set in each subclass and holds a description of the beverage like: “Most Excellent Dark Roast”.

The cost ( ) method is abstract; subclasses need to define their own implementations.

Each subclass implements cost ( ) to return the cost of the beverage

Page 133: Chapter 2

Adding on…. In addition to your coffee you can also ask for several condiments like steamed

milk, soy, mocha etc. Starbuzz charges a bit for each of these so they really need to get them built into the order system. First attempt…..

DarkRoastWithSoyAndMocha cost ()

DarkRoastWithSteamedMilkAndMocha cost ()

HouseBlend cost ()

Beverage description getDescription ( ) cost ( ) // other useful methods

HouseBlendWithSteamedMilkandMocha cost ()

DarkRoastWithSteamedMilkAndMocha cost ()

HouseBlendWithSteamedMilk cost ()

DarkRoastWithSteamedMilk cost ()

DecafWithSteamedMilkAndMocha cost ()

DecafWithSteamedMilkAndMocha cost ()

ExpressoWithWhipandSoy cost ()

DarkRoastWithWhip cost ()

Each cost method computes the cost of the coffee along with other condiments in the order.

Can you say “Class Explosion” !!!!

Page 134: Chapter 2

Question

It is pretty obvious that Starbuzz has created a maintenance nightmare for themselves. What happens when the price of milk goes up? Or when they add a new caramel topping?

Beyond the maintenance problem -- what OO design principle(s) are they violating here?

Page 135: Chapter 2

Alternatives to the Design?Can’t we just use instance variables and inheritance in the superclass to keep track of the condiments?

New boolean values for each of the condiments

Now we implement the cost ( ) in Beverage (instead of keeping it abstract), so that it can calculate costs associated with the condiments for a particular beverage instance. Subclasses will still override the cost ( ), but they will also invoke the super version so that they can calculate the total cost of the basic beverage plus the cost of the added condiments.

Beverage description milk soy mocha whip

getDescription ( ) cost ( )

hasMilk ( ) setMilk ( ) hasSoy ( ) setSoy ( ) // and others

These get and set the boolean values for the condiments.

HouseBlend cost ( )

DarkRoast cost ( )

Decaf cost ( )

Expresso cost ( )

Page 136: Chapter 2

Is this ok?

What requirements or other factors might change that will impact this design?

1) Price changes for condiments will force us to alter the existing code2) New condiments will force us to add new methods and alter the cost method in the superclass.3) We may have new beverages. For some of these beverages the condiments may not be appropriate4) What if a customer wants a double mocha?

What else?

Page 137: Chapter 2

Meet the Decorator Pattern

We start with a beverage and “decorate” it with the condiments at runtime. If a customer wants a Dark Roast with Mocha and Whip we do the following:

1. Take a DarkRoast object

2. Decorate it with a Mocha object

3. Decorate it with a Whip object

4. Call the cost ( ) method and rely on delegation to add on the condiment costs.

How do you “decorate” and how does delegation come into this?

Page 138: Chapter 2

Constructing a drink order with Decorators1. Start with the DarkRoast object

2. Customer wants Mocha, so we create a Mocha object and wrap it around the DarkRoast.

3. The customer also wants Whip, so we create a Whip decorator and wrap Mocha with it.

cost ( )

DarkRoast inherits from Beverage and has a cost ( ) method that computes the cost of the drink.

cost ( ) cost ( )

The Mocha object is a “decorator”. Its type mirrors the object it is decorating, in this case, a Beverage. (“mirror” means it is the same type.

So Mocha has a cost ( ) method too, and through polymorphism we can treat any Beverage object wrapped in Mocha as a Beverage too. (Mocha is a subtype of Beverage)

cost ( ) cost ( ) cost ( )

Whip is a decorator, so it also mirrors DarkRoast’s type and includes a cost ( ) method.

So DarkRoast wrapped in Mocha and Whip is still a Beverage and we can do anything with it that we can do with a DarkRoast, including call its cost ( ) method.

Page 139: Chapter 2

Constructing a drink order with Decorators4. Now its time to compute the cost for the customer. Do this by calling

cost( ) on the outermost decorator, Whip, and Whip is going to delegate computing cost to the objects it decorates. Once it gets a cost, it will add on the cost of the Whip.

cost ( ) cost ( ) cost ( )

(1) First we call cost ( ) on the outermost decorator, Whip.

0.991.190.10$1.29

(2) Whip calls cost ( ) on Mocha

(3) Mocha calls cost ( ) on DarkRoast

(4) DarkRoast returns its cost, 99 cents

(5) Mocha adds its cost, 20 cents, to the result and returns the new total $1.19

(6) Whip adds its total, 10 cents, to the result from Mocha, and returns the final result -- $1.29.

Page 140: Chapter 2

So what do we know so far?

Decorators have the same supertype as the objects that they decorate.

You can use one or more decorators to wrap an object. Given that the decorator has the same supertype as the object it

decorates, we can pass around a decorated object in place of the original object.

The decorator adds its own behavior either before and/or after delegating to the object its decorates to do the job.

Objects can be decorated at any time, so we can decorate objects at runtime with as many decorators as we like.

Key point!

Page 141: Chapter 2

Decorator Pattern DefinedThe Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Component methodA ( ) methodB ( ) // other methods

ConcreteComponent

methodA ( )methodB ( )// other methods

Decorator

methodA ( ) methodB ( ) // other methods

ConcreteDecoratorA

Component wrappedObject

methodA ( ) methodB ( ) newBehavior ( ) // other methods

ConcreteDecoratorB

Component wrappedObject Object newState

methodA ( ) methodB ( ) // other methods

Each component can be used on its own or wrapped by a decorator component.

Each decorator HAS_A (wraps) a component, which means the decorator has an instance variable that holds a reference to a component.

Decorators implement the same interface or abstract class as the component they are going to decorate.

Decorators can extend the state of the component

The ConcreteDecorator has an instance variable for the thing it decorates (the Component the Decorator wraps)

Decorators can add new methods; however, new behavior is typically added by doing some computation before or after an existing method in the component

The ConcreteComponent is the object we are going to dynamically add new behavior to. It extends the Component.

Page 142: Chapter 2

Decorate the Beverages! Beverage

description getDescription ( ) cost ( ) // other methods

HouseBlend cost ( )

DarkRoast cost ( )

Expresso cost ( )

Decaf cost ( )

CondimentDecorator getDescription ( )

Milk Beverage beverage cost ( ) getDescription ( )

Mocha Beverage beverage cost ( ) getDescription ( )

Soy Beverage beverage cost ( ) getDescription ( )

Whip Beverage beverage cost ( ) getDescription ( )

Beverage acts as our abstract Component class

The four concrete components, one per coffee type.

The condiment decorators. Notice they need to implement the cost () as well as the getDescription ( ).

component

Page 143: Chapter 2

Some Real Code! public abstract class Beverage { String description = “Unknown Beverage”; public String getDescription ( ) { return description; } public abstract double cost ( );}

public abstract class CondimentDecorator extends Beverage { public abstract String getDescription ( ); }

Beverage is an abstract class with two methods getDescription ( ) and cost ( ).getDescription ( )is already implemented, but we need to implement cost ( ) in the subclasses.

First, we need to be interchangeable with Beverage, so we extend the Beverage class.

We are also going to require that the condiment decorators reimplement the getDescription ( ) method. We will see why in a sec…

Page 144: Chapter 2

Coding Beverages public class Expresso extends Beverage { public Expresso ( ) { description = “Expresso”; } public double cost ( ) { return 1.99; }}

public class HouseBlend extends Beverage { public HouseBlend ( ) { description = “HouseBlend”; } public double cost ( ) { return .89; } }

Page 145: Chapter 2

Coding Condiments public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public String getDescription ( ) { return beverage.getDescription( ) + “, Mocha”; } public double cost ( ) { return .20 + beverage.cost ( ); }} We want our description to say not

only Dark Roast -- but to also include the item decorating each beverage for instance: Dark Roast, Mocha. So we first delegate to the object we are decorating to get its description, then append “, Mocha” to that description.

Similarly, to compute the cost of the beverage with Mocha, we first delegate to the object that is being decorated, so that we can compute its cost and then add in the cost of the Mocha.

Page 146: Chapter 2

Ordering Coffee public class StarbuzzCoffee { public static void main (String args[]) { Beverage beverage = new Espresso ( ); System.out.println ( beverage.getDescription ( ) + “ $ “ + beverage.cost ( )); Beverage beverage2 = new DarkRoast ( ); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip (beverage2); System.out.println( beverage.getDescription ( ) + “$ “ + beverage2.cost ( )); }}

Page 147: Chapter 2

Real World Decorators

The java.io package uses the Decorator pattern!

InputStream

FileInputStream StringBufferInputStream ByteArrayInputStream FilterInputStream

BufferedInputStream

DataInputStream

LineNumberInputStream

PushbackInputStream

Heres the abstract component

FilterInputStream is an abstract decorator

These InputStreams are the ConcreteComponents. There are a few more that are not shown here.

Here are the concrete decorators.

Page 148: Chapter 2

The java.io Package (contd.) What is the typical set of objects that use decorators to add

functionality to reading data from a file?

100111101000010101010111

A Text File

FileInputStream is the component that’s being decorated. The Java I/O library supplies several components, including FileInputStream, StringBufferInputStream, and others. All of these give us the base component from which to read bytes.

BufferedInputStream is a concrete Decorator . BufferedInputStream adds behavior in two ways: it buffers input to improve performance, and also augments the interface with a new method readLine ( ) for reading character-based input, a line at a time.

LineNumberInputStream is also a concrete decorator. It adds the ability to count the line numbers as it reads data.

Page 149: Chapter 2

Exercise your brains…

How would you write a decorator that converts all uppercase characters to lowercase in the input stream?

Combining patterns: We have already seen a much better way of creating objects. How would you apply the Factory methods to create decorator objects?

Page 150: Chapter 2

Exercise your brain…

What would a good example of where Decorator patterns would be useful in your game?

Page 151: Chapter 2

Summary Decorator patterns are based on the open-closed principle!

– We should allow behavior to be extended without the need to modify existing code.

The Decorator Pattern – Provides an alternative to subclassing for extending behavior.– Involves a set of decorator classes that are used to wrap concrete

components– Decorator classes mirror the types of the components they decorate.– Decorators change the behavior of their components by adding new

functionality before and/or after method calls to the component.– You can wrap a component with any number of decorators.– Decorators are typically transparent to the client of the component -- unless

the client is relying on the component’s concrete type.– Decorators can result in many small objects in our design, and overuse can

be complex!

Page 152: Chapter 2

Factory Patterns

“Baking with OO Goodness”

Page 153: Chapter 2

Factory Patterns

Factory patterns are examples of creational patterns Creational patterns abstract the object instantiation

process. – Hide how objects are created– Make system independent of how its objects are created and

composed. Class creational patterns focus on the use of inheritance

to decide on the object to be instantiatedFactory method

Object creational patterns focus on the delegation of the instantiation to another objectAbstract Factory

Page 154: Chapter 2

“new” = “concrete”

Design Principle: “Don’t program to an implementation, program to an abstraction”

However, every time you do a “new” you need to deal with a “concrete” class, not an abstraction.Duck duck = new MallardDuck ( );

We want to use interfaces to keep code flexible

But we have to create an instance of a concrete class

With a whole set of related concrete classes:Duck duck; if (picnic) duck = new MallardDuck (); else if (hunting) duck = new DecoyDuck ( ); else if (inBathTub) duck = new RubberDuck ( );}

Whats wrong with this? What principle is broken here?

Page 155: Chapter 2

What can you do?

Principle: Identify the aspects that vary and separate them from what stays the same.

How might you take all the parts of your application that instantiate concrete classes and separate or encapsulate them from the rest of your application?

Page 156: Chapter 2

Identifying aspects that VaryOwn a pizza store in cutting edge Objectville!

Pizza orderPizza ( ) { Pizza pizza = new Pizza ( ); pizza.prepare () ; pizza.bake (); pizza.cut (); pizza.box (); return pizza;}

For flexibility it would be nice if this wasn’t concrete, but we can’t instantiate abstract classes!

Page 157: Chapter 2

Identifying Aspects that Vary (2/ But you need more than one type of pizza:Pizza orderPizza ( String type) { Pizza pizza; if (type.equals (“cheese”) { pizza = new CheesePizza (); } else if (type.equals(“greek”)) { pizza = new GreekPizza ( ); } else if (type.equals(“pepperoni”) { pizza = new PepperoniPizza ( ); }

pizza.prepare () ; pizza.bake (); pizza.cut (); pizza.box (); return pizza;}

Instantiate based on type of pizza

Pass in the type of Pizza to orderPizza( )

Prepare the pizza

Page 158: Chapter 2

But the pressure is on to add more pizza types…. Need to add a couple trendy pizzas to their menu: Clam and

Veggie. Greek is not selling so well - so take it out!

What do you think would need to vary and what would stay constant?

Page 159: Chapter 2

Modified orderPizza ( )Pizza orderPizza ( String type) { Pizza pizza; if (type.equals (“cheese”) { pizza = new CheesePizza (); } else if (type.equals(“greek”)) { pizza = new GreekPizza ( ); } else if (type.equals(“veggie”)) { pizza = new VeggiePizza ( ); } else if (type.equals(“pepperoni”) { pizza = new PepperoniPizza ( ); }

pizza.prepare () ; pizza.bake (); pizza.cut (); pizza.box (); return pizza;}

This is what varies

This is what we expect will stay the same

This code is not closed for modification!

Page 160: Chapter 2

Encapsulating Object Creation

Move the object creation out of the orderPizza ( ) method. How?

– Move the creation code into a special purpose object that is concerned with only creating pizzas

Pizza orderPizza ( String type) { Pizza pizza; pizza.prepare () ; pizza.bake (); pizza.cut (); pizza.box (); return pizza;}

if (type.equals (“cheese”) { pizza = new CheesePizza (); } else if (type.equals(“greek”)) { pizza = new GreekPizza ( ); } else if (type.equals(“veggie”)) { pizza = new VeggiePizza ( ); } else if (type.equals(“pepperoni”) { pizza = new PepperoniPizza ( ); }

Pull it out

We place this code into a separate object SimplePizzaFactory

What’s going to go here?

Page 161: Chapter 2

Building a Simple Pizza Factory public class SimplePizzaFactory { public Pizza createPizza (String type ) { Pizza pizza = null;

if (type.equals (“cheese”) ) { pizza = new CheesePizza (); } else if (type.equals(“greek”)) { pizza = new GreekPizza ( ); } else if (type.equals(“veggie”)) { pizza = new VeggiePizza ( ); } else if (type.equals(“pepperoni”) { pizza = new PepperoniPizza ( ); }}

Code is still parameterized by the type of pizza, just like the original code.

Factories handle the details of the object creation.

Here’s code we plucked out of the orderPizza() method.

Could this method be made static?

Page 162: Chapter 2

Reworking the PizzaStore class public class PizzaStore { SimplePizzaFactory factory;

public PizzaStore(SimplePizzaFactory factory) {this.factory = factory;

}public Pizza orderPizza (String type){

Pizza pizza;pizza = factory.createPizza (type);pizza.prepare () ;pizza.bake ();pizza.cut ();pizza.box ( );return pizza;

}}

New operator replaced by create method!

PizzaStore has a reference to the factory

PizzaStore gets the factory passed in the constructor

Page 163: Chapter 2

Why is this better?

SimplePizzaFactory may have many more clients than orderPizza ( ) method– PizzaShopMenu, HomeDelivery etc.

Client code does not have any concrete classes anymore!!

SimpleFactory is not really a design pattern but the actual Factory patterns are based on it!

Page 164: Chapter 2

SimpleFactory Pattern

PizzaStore SimplePizzaFactoryPizza

prepare( ) bake ( ) cut ( ) box ( )

CheesePizza

VegiePizza ClamPizza

PepperoniPizza

Client of the factory. Goes through factory to get instances of Pizza

This is the factory where we create pizzas; this should be the only part of our application that refers to concrete Pizza classes.

Product of the factory (abstract)

Concrete products. Each product needs to implement the Pizza interface.

Abstract class with some helpful implementations that can be overridden.

createPizza ()

createPizza ()

create method sometimes declared static.

Page 165: Chapter 2

Onwards with the Pizza Franchise

Franchises in different cities– Must ensure quality of pizza– Must account for regional differences (NY, Chicago..)

Want franchise store to leverage your PizzaStore code --> pizzas are prepared the same way

NY needs a factory that makes NY style pizza Chicago needs a factory that makes Chicago style pizza

One approach --> SimpleFactory

Page 166: Chapter 2

Applying SimpleFactory Pattern

NYPizzaFactory nyFactory = new NYPizzaFactory ( );

PizzaStore nyStore = new PizzaStore (nyFactory); nystore.order (“Veggie”);

ChicagoPizzaFactory CFactory = new ChicagoPizzaFactory ( ); PizzaStore CStore = new PizzaStore (CFactory); Cstore.order (“Veggie”);

Issues:• Franchises using your factory to create pizza, but using homegrown procedures for baking etc.• Yet, each franchise “needs room for adding own improvements”

•You don’t want to know what they put on their pizza - detail that should be “exposed” only to the individual stores. Yet you want to have some control (quality control!)

What is needed is a framework that ties the store and pizza creation together, yet allows for flexibility.

Here we create a factory for making NY style pizza

Then we create a PizzaStore and pass it a reference to the NY factory

…and when we make pizzas we get NY style pizzas

Page 167: Chapter 2

Need a mechanism to “localize” all pizza making activities to the PizzaStore class and yet give franchises freedom to have their own regional style!

A Framework

public abstract class PizzaStore { public Pizza orderPizza (String type) { Pizza pizza; pizza = createPizza (type);

pizza.prepare ( ); pizza.bake ( ); pizza.cut ( ); pizza.box ( );

return pizza; }

abstract createPizza (String type); }

Now createPizza is back to being a call to a method in the PizzaStore rather than a Factory object!

All this is the same. Break out into orderPizza ( ) method.

Our factory method is now abstract in PizzaStore.

Allows each individual subclass to decide which Factory to invoke.All subclasses MUST implement the createPizza method.

Page 168: Chapter 2

Allowing the subclasses to decide…PizzaStore

createPizza( ) orderPizza ( )

NYStylePizzaStore

createPizza( )

ChicagoStylePizzaStore

createPizza( )

Each subclass overrides the createPizza ( ) method, while all subclasses make use of the orderPizza () method defined in the PizzaStore.

If franchise wants NY style pizzas for its customers, it uses the NY subclass, which has its own createPizza ( ) method, creating NY style pizzas.

public Pizza createPizza (type) { if (type.equals(“cheese”)) pizza = new NYStyleCheesePizza ( ); else if (type.equals (“pepperoni”)) pizza = new NYStylePepperoniPizza ( ); }

createPizza () returns a Pizza and the subclass is fully responsible for which concrete Pizza it instantiates

Here’s where the concrete classes are being created!

Note: orderPizza ( ) method in superclass has no clue which Pizza we are creating. It only knows it can prepare, bake, cut and box it!

Page 169: Chapter 2

A Factory Method Up Close!

A “Factory” method handles object creation and encapsulates it in a subclass. This decouples the client code in the superclass from the object creation code in the subclass.

abstract Product factoryMethod (String type)

A factory method is abstract so the subclasses are counted on to handle object creation.

A factory method returns a Product that is typically used within methods defined in the superclass.

A factory method isolates the client (the code in the superclass, like orderPizza ( )) from knowing what kind of concrete Product is actually created.

A factory method may or may not be parameterized to select among several variations of a product.

Page 170: Chapter 2

Factory Method Pattern

All factory patterns encapsulate “object creation” Factory method pattern encapsulates object creation by letting

subclasses decide what objects to create. Who are the players in this pattern?

Page 171: Chapter 2

The Players!

The Product Classes The Creator Classes

Notice the parallel class hierarchies: both have abstract classes that are extended by concrete classes, which know about specific implementations for NY and Chicago.

Pizza

NYStyleCheesePizzaNYStylePepperoniPizza

NYStyleClamPizzaNYStyleVeggiePizza

CStyleCheesePizzaCStylePepperoniPizza

CStyleClamPizzaCStyleVeggiePizza

PizzaStore

NYPizzaStore

ChPizzaStore

Factory method is key to encapsulating this knowledge!

NYPizzaStore & CPizzaStore encapsulate all the knowledge about how to make NY Style Pizzas and Chicago Style Pizzas respectively.

Page 172: Chapter 2

Factory Method Pattern Defined

All products must implement the same interface so that the classes which use the products can refer to the interface, not the concrete class.

The ConcreteCreator is responsible for creating one or more concrete products. It is the only class that has knowledge of how to create these products.

The ConcreteCreator implements the factoryMethod ( ), which is the method that actually produces the products.

The abstract factoryMethod ( )is what all Creator subclasses must implement.

The Creator is the class that contains the implementations for all the methods to manipulate the products, except for the factory method!

The Factory Method Pattern defines an interface for creating an object but lets the subclasses decide which class instantiate. Factory method lets a class defer instantiation to subclasses.

Why decides?

Page 173: Chapter 2

Meanwhile, back at the PizzaStore….

Things are going good, but you have learned that a few franchises are substituting inferior ingredients -> bringing down the Objectville name!

How are you going to ensure each factory is using quality ingredients? – You are going to build a factory that produces them and ships

them to your franchises!– One problem: franchises are located in different regions so what

is red sauce in NY is not red sauce in Chicago! So: same product families (dough, cheese, sauce etc.) but

different implementations based on region.

Page 174: Chapter 2

Building the Ingredient Factory Ingredient factory: creates each ingredient in the ingredient family (but does

not handle regional differences yet!)

public Interface PizzaIngredientFactory { public Dough createDough ( ); public Sauce createSauce ( ); public Cheese createCheese ( ); public Veggies [ ] createVeggies ( ); public Pepperoni createPepperoni ( ); public Clams createClams ( ); }

For each ingredient we define a create method in our interface.

Lots of new classes here, one per ingredient

If we had some common “machinery” to implement in each instance of factory, we could have made this abstract instead.

What to do next?1. Build a factory for each region. To do this, create a subclass of PizzaIngredientFactory

that implements each create method.2. Implement a set of ingredient classes to be used with the factory, like RedPeppers,

ThickCrustDough, etc. These classes can be shared among regions where appropriate.3. Then we still need to hook all this up by working our new ingredient factories into the old

PizzaStore code.

Page 175: Chapter 2

(1) The New York Ingredient Factory

public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough ( ){ return new ThinCrustDough ( ); } public Sauce createSauce ( ){ return new MarinaraSauce ( ); } public Cheese createCheese ( ) { return new ReggianoCheese ( ); } public Veggies [ ] createVeggies ( ){ Veggies veggies[ ] = { new Garlic ( ), new Onion ( ), new Mushroom ( )}; return veggies; } // other ingredients }

The NY ingredient factory implements the interface for all ingredient factories

For each ingredient in the ingredient family, we create the NY version.

Page 176: Chapter 2

Reworking the Pizzas public abstract class Pizza { String name;

Dough dough;Sauce sauce;Veggies veggies[];Cheese cheese;Pepperoni pepper;Clams clams;

abstract void prepare ( );void bake ( ) {

System.out.println ( “Bake for 25 minutes at 350”);}

void cut ( ) { }void box ( ) { }void setName (String name) { this.name = name;}String getName ( ) { return name; }}

}

Each pizza holds a set of ingredients that are used in its prep.

The prepare () method is abstract. This is where we are going to collect the ingredients needed for the pizza which will come from the ingredient factory.

Other methods remain the same

Page 177: Chapter 2

Reworking the Pizzas (contd.) public class CheesePizza extends Pizza {

PizzaIngredientFactory ingredientFactory;

public CheesePizza ( PizzaIngredientFactory ingredientFactory) {this.ingredientFactory = ingredientFactory;

}

void prepare ( ){System.out.println (“Preparing: “ + name );dough = ingredientFactory.createDough ( );sauce = ingredientFactory.createSauce ( );cheese = ingredientFactory.createCheese ( );

}}

Here’s where the magic happens!

To make a pizza now, we need a factory to provide the ingredients. So each class gets a factory passed into its constructor, and its stored in an instance variable.

The prepare ( ) method steps through the creating a cheese pizza, and each time it needs an ingredient, it asks the factory to produce it.

Page 178: Chapter 2

Code Up Close!

sauce = ingredientFactory.createSauce ( );

We are setting the pizza instance variable to refer to the specific sauce used in this pizza

This is the ingredient Factory. The pizza does not care which factory is used, as long as it is an ingredient factory.

The createSauce () method returns the sauce that is used in its region. If this is NY ingredient factory, then we get marinara sauce.

Page 179: Chapter 2

Revisiting the Pizza Store public class NYPizzaStore extends PizzaStore {

protected Pizza createPizza (String item) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory ( );

if (item.equals(“cheese”)){pizza = new CheesePizza (ingredientFactory);pizza.setName(“New York Style Cheese Pizza”);

} else if (item.equals(“veggie”)){pizza = new VeggiePizza (ingredientFactory);pizza.setName (“New York Style Veggie Pizza”);

} // same for all other pizza types. return pizza; }}

The NY Store is composed with a NY pizza ingredient factory. This will be used to produce the ingredients for all NY style pizzas.

We now pass each pizza the factory that should be used to produce its ingredients.

For each type of pizza we instantiate a new Pizza and give it the factory that it needs to get its ingredients.

Page 180: Chapter 2

What have we done? We provided a means of creating a

family of ingredients for pizzas by introducing a new type of factory called -- Abstract Factory.

Abstract Factory:– Gives an interface for creating a

family of products.– By writing code that uses this

interface we decouple our code from the actual factory that creates the products.

– Allows us to implements a variety of factories that produce products meant for different contexts.

– Decoupling --> enables substitution of different factories to get different behaviors.

Defines the interface

Objectville Abstract IngredientFactory

NY Chicago

Provides implementations for products

Pizza Store

Pizza made with ingredients produced by the concrete factory

Page 181: Chapter 2

The Abstract Factory Pattern

The AbstractFactory defines the interface that all Concrete factories must implement, which consists of a set of methods for producing products.

The concrete factories implement the different product families. To create a product, the client uses one of these factories, so it never has to instantiate a product object.

This is the product family. Each concrete factory can produce an entire set of objects.

The client is written against the abstract factory and then composed at runtime with an actual factory.

The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Page 182: Chapter 2

Summary All factories encapsulate object creation Simple factory, while not a bona fide design pattern, is a simple way to decouple

your clients from concrete classes. Factory method relies on inheritance: object creation is delegated to subclasses

which implement the factory method to create objects Abstract Factory relies on object composition: object creation is implemented in

methods exposed in the factory interface. All factory methods promote loose coupling by reducing the dependency of your

application on concrete classes. The intent of Factory method is to allow a class to defer instantiation to its

subclasses. The intent of the Abstract Factory is to create families of related objects without

having to depend on their concrete classes. The Dependency Inversion principle guides us to avoid dependencies on concrete

types and to strive for abstractions. Factories are a powerful technique for coding to abstractions, not concrete classes.

Page 183: Chapter 2

The Singleton Pattern

“One of a Kind Objects”

Page 184: Chapter 2

What is this?

Singleton: How to instantiate just one object - one and only one! Why?

– Many objects we need only one of: thread pools, caches, dialog boxes, objects that handle preferences and registry settings etc.

– If more than one instantiated: • Incorrect program behavior, overuse of resources, inconsistent results

Alternatives:– Use a global variable

• Downside: assign an object to a global variable then that object might be created when application begins. If application never ends up using it and object is resource intensive --> waste!

– Use a static variable• Downside: how do you prevent creation of more than one class object?

Page 185: Chapter 2

The Little SingletonHow would you create a single object?

And what if another object wanted to create a MyObject? Could it call new on MyObject again?

Can we always instantiate a class one or more times?

And if not?

Is this possible?

public MyClass { private MyClass ( ) { } }

What does it mean?

new MyObject ( );

Yes.

Yes. Caveat: Only if it is public class

Only classes in the same package can instantiate it - but they can instantiate it more than once.

Yes. It is a legal definition

A class that can’t be instantiated because it has a private constructor

Page 186: Chapter 2

The Little Singleton (contd.)

Is there any class that could use a private constructor? What’s the meaning of the following?

Instantiating a class with a private constructor:

public MyClass { public static MyClass getInstance ( ) { } }

public MyClass { private MyClass ( ) { } public static MyClass getInstance ( ) { } }

Page 187: Chapter 2

The Classic Singleton Pattern public class Singleton { private static Singleton uniqueInstance; // other useful instance variables

private Singleton ( ) { } public static Singleton getInstance ( ) { if (uniqueInstance == null) { uniqueInstance = new Singleton

( ); } return uniqueInstance; }

// other useful methods }

We have a static variable to hold our one instance of the class Singleton.

Constructor is declared private; only singleton can instantiate this class!

The getInstance ( ) method gives us a way to instantiate the class and also return an instance of it.

Of course, Singleton is a regular class so it has other useful instances and methods.

Page 188: Chapter 2

Code Up Close

if (uniqueInstance == null) { uniqueInstance = new Singleton ( ); } return uniqueInstance;

uniqueInstance holds our ONE instance; remember it is a static variable

If uniqueInstance is null, then we haven’t created the instance yet…

…and if it doesn’t exist, we instantiate Singleton through its private constructor and assign it to the uniqueInstance. Note that if we never need the uniqueInstance, it never gets created -->

lazy instantiation.

If uniqueInstance wasn’t null, then it was previously created. We just fall through to the return statement. In either case, we have an instance and we return it.

Page 189: Chapter 2

Singleton Pattern DefinedThe Singleton Pattern ensures a class has only one instance, and provides a global point of access to it.

Singleton

static uniqueInstance // other useful variables

static getInstance ( ) // other methods

The getInstance ( ) method is static, which means it is a class method, so you can conveniently access this method anywhere in your code using Singleton.getInstance ( ). That’s just as easy as accessing a global variable, but we get benefits like lazy instantiation from the Singleton.

The uniqueInstance class variable holds our one and only one instance of Singleton.

A class implementing a Singleton Pattern is more than a Singleton; it is a general purpose class with its own set of data and methods.

Page 190: Chapter 2

Houston, we have a problem….

We improved the Chocolate Boiler code with the Singleton pattern and we added some optimizations to the Chocolate Boiler Controller that makes use of multiple threads

Ugh… the Chocolate Boiler’s fill ( ) method was able to start filling the boiler even though a batch of milk and chocolate was already boiling! That’s 500 gallons of milk and chocolate spilled.

Could the addition of threads have caused this?

Hershey, PA

Page 191: Chapter 2

Be the JVM

We have two threads each executing this code: Chocolate Boiler boiler = ChocolateBoiler.getInstance ( ); fill ( ); boil ( ); drain ( );

Could the two threads get hold of different boiler objects?

public static ChocolateBoiler getInstance ( ){ if (uniqueInstance == null){ uniqueInstance = new ChocolateBoiler ( ); } return uniqueInstance; }

Page 192: Chapter 2

Dealing with Multi-threading

Easy fix: make getInstance ( ) a synchronized method

public class Singleton { private static Singleton uniqueInstance; // other useful instance variables

private Singleton ( ) { } public static synchronized Singleton getInstance ( ) { if (uniqueInstance == null) { uniqueInstance = new Singleton ( ); } return uniqueInstance; }

// other useful methods }

By adding the synchronized keyword to getInstance ( ) method, we force every thread to wait its turn before it can enter the method. That is, no two threads may enter the method at the same time.

This fixes the problem, but synchronization is expensive; is this really an issue? -- synchronization is really only needed the first time through this method. Once we have created the first Singleton instance, we have no further need to synchronize this method. So after the first time, synchronization is totally unneeded overhead.

Page 193: Chapter 2

public class Singleton { private static Singleton uniqueInstance = new Singleton ( );

private Singleton ( ) { } public static Singleton getInstance ( ) { return uniqueInstance; }}

Can we improve multithreading?

1. Do nothing if the performance of getInstance ( ) isn’t critical to your application. [ remember that synchronizing can decrease performance by a factor of 100]

2. Move to an eagerly created instance rather than a lazily created one.

Go ahead and create an instance of Singleton in a static initializer. This code is guaranteed to be thread safe!

We’ve already got an instance, so just return it.

Page 194: Chapter 2

Can we improve multithreading?3. Use “double-locking” to reduce the use of synchronization in

getInstance ()

• First check to see is instance is created, THEN synchronize. public class Singleton { private volatile static Singleton uniqueInstance; // other useful instance variables

private Singleton ( ) { } public static Singleton getInstance ( ) { if (uniqueInstance == null) { synchronized (Singleton.class) { if (uniqueInstance == null ){ uniqueInstance = new Singleton ( ); } } } return uniqueInstance; } }

Check for an instance and if there isn’t one, enter the synchronized block.

Note we only synchronize the first time through.

Once in the block, check again if null. If so create instance.

The volatile keyword ensures that multiple threads handle uniqueInstance variable correctly when it is being initialized to the Singleton instance.Only JDK 1.5!

If performance is an issue then this method can drastically reduce overhead!

Page 195: Chapter 2

Summary The Singleton Pattern ensures you have at most one instance of a class in your

application The Singleton Pattern also provides a global access point to that instance. Java’s implementation of the Singleton Pattern makes use of a private

constructor, a static method combined with a static variable Examine your performance and resource constraints and carefully choose an

appropriate Singleton implementation for multi-threaded applications. Beware of double-checked locking implementation -- it is not thread-safe pre

JDK 1.5 Be careful if you are using multiple class loaders -- this can defeat the purpose

of the Singleton implementation If you are using a JVM earlier than 1.2, you’ll need to create a registry of

Singletons to defeat the garbage collector.

Page 196: Chapter 2

The Command Pattern

Encapsulating Invocation

Page 197: Chapter 2

Command Pattern

Encapsulates method invocation - Purpose:

– crystallize pieces of computation so that the objects invoking the computation do not have to worry about how to do things - they just use the crystallized method!

– Can also do some “wickedly smart” things with these encapsulated methods like save them for logging or reuse them to implement “undo”

Page 198: Chapter 2

A Motivating Example

Goal: Program a Remote Control that can be used to control the devices in the house

Requirements:– Remote control features seven programmable slots– Each slot can be assigned to a different household device– Each slot has a corresponding on/off button– Remote has a global undo button that undoes the last button

pressed.– A set of vendors classes are provided to give you an idea of

the interfaces of the objects that need to be controlled from the remote.

Page 199: Chapter 2

A Pictorial View

on Off

Seven slots to programEach slot contains a different device and is controlled via the buttons.

On and off buttons for each of the seven slots

These two control device 1

Global “undo” button

CeilingLight on ( ) off ( ) dim ( )

TV on ( ) off ( ) setInputChannel ( ) setVolume ( )

FaucetControl openValue ( ) closeValue ( )

Thermostat setTemperature ( )

Hottub circulate ( ) jetsOn ( ) jetsOff ( ) setTemperature ( )

Vendor Classes

Page 200: Chapter 2

Observations, anyone? Expectation: see a bunch of classes with on ( ) and off ( ) methods -->

common interface Instead: each vendor class has its own API: dim ( ), setTemperature ( ),

setVolume ( ), setDirection ( ) Observation:

– Separation of concerns: remote should know how to interpret button presses and make requests, but it really should not know anything about home automation or how to turn on a hot tub.

– Any issues?

Requirement: There will be more vendor classes in the future - design must accommodate for that

If the remote is dumb, how do we design a remote so that it can invoke an action - turn on a light?

Page 201: Chapter 2

Enter -- The Command Pattern! Command Pattern allows you to decouple the requester of an

action from the object that actually performs the action– Requester == remote control, Object == vendor classes

How does it work?– Introduce “command objects” into your design. A command object

encapsulates a request to do something (like turn on a light) on a specific object (say, the living room light).

– Every time a remote button is pressed, its corresponding command object goes to work!

– Remote does not have any idea what the work is, it just has a command object that knows how to talk to the right object to get the work done.

– Here the remote is decoupled from the object!

Page 202: Chapter 2

A Diner Example - A Brief Introduction to the Command Pattern

(1) You, the Customer give the Waitress your Order

Order

(2) The Waitress takes the Order, places it on the order counter and says “Order up!”

(3) The Short-Order Cook prepares your meal from the Order.

Page 203: Chapter 2

Ordering in Objectville

The customer knows what he/she wants and creates an order

order

takeOrder ( )

createOrder ( )

The Waitress takes the Order, and when she gets around to it, she calls its orderUp ( ) method to begin the Order’s preparation.

order

The Order has all the instructions needed to prepare the meal. The Order directs the Short Order Cook with methods like makeBurger ( ).

The Short Order Cook follows the instructions of the Order and produces the meal.

Start Here

Page 204: Chapter 2

The Objectville Diner Objects and Responsibilities

Order Slip: encapsulates a request to prepare a meal Waitress: take the Order Slips and invoke the

orderUp ( ) method on them The Short Order Cook: has the knowledge required

to prepare the meal!

Page 205: Chapter 2

From the Diner to the Command Pattern

create Command object ( )

The client is responsible for creating the command object. The command object consists of a set of actions on a receiver

public void execute { receiver.action1 (); receiver.action2 (); }

action1( ) action2( )

The actions and the Receiver are bound together in the command object.

The Command Object provides one method, execute ( ), that encapsulates the actions and can be called to invoke the actions on the Receiver.

execute ( )

(1) createCommandObject ( )

(2) setCommand ( )

The client calls setCommand ( ) on an Invoker object and passes it the command object, where it gets stored until it is needed.

setCommand ( )

execute ( )At some point in the future the Invoker calls the Command object’s execute () method.

execute ( )

action1 ( ) action2 ( ) action1 () , action2 ( )

…which results in the actions being invoked on the Receiver

(3) Loading the Invoker(1) The client creates a

command object.(2) The client does a

setCommand ( ) to store the command object in the invoker.

(3) Later… the client asks the invoker to execute the command . Note: once the command is loaded into the invoker, it may be used and discarded or it may remain and be used many times.

Start here

Page 206: Chapter 2

Coding Our First Command Object (1/3)

Implementing the Command Interface: public interface Command { public void execute ( ); }

Implementing a Command to turn the light on public class LightOnCommand implements Command { Light light; public LightOnCommand (Light light) { this.light = light; } public void execute ( ) { light.on ( ); } }

Simple. All we need is one method called execute ( ).

This is a command, so we need to implement the Command interface.

The constructor is passed the specific light that this command is going to control - say the living room light - and stashes it in the light instance variable. When execute ( ) gets called, this is the light object that is going to be the Receiver of the request.

The execute method calls the on ( ) method on the receiving object, which is the light that we are controlling.

Page 207: Chapter 2

Coding the First Command Object (2/3)

Using the Command Object public class SimpleRemoteControl {

Command slot; public SimpleRemoteControl ( ) { } public void setCommand (Command command) { slot = command; } public void buttonWasPressed ( ) { slot.execute ( ); } }

We have one slot to hold our command, which will control one device.

We have a method for setting the command the slot it’s going to control. This could be called multiple times if the client of this code wanted to change the behavior of the remote button.

This method is called when the button is pressed. All we do is take the current command bound to the slot and call its execute ( ) method.

Page 208: Chapter 2

Coding the First Command Object (3/3)

Creating a Simple test to use the Remote Control

public class RemoteControlTest {

public static void main (String [] args) { SimpleRemoteControl remote = new SimpleRemoteControl ( ); Light light = new Light ( ); LightOnCommand lightOn = new LightOnCommand (light);

remote.setCommand (lightOn);

remote.buttonWasPressed ( ); }}

This is our client in Command Pattern-speak

The remote is our Invoker; it will be passed a command object that can be used to make requests.

Now we create a Light Object - this will be the Receiver of the request.

Here, create a command and pass it to the Receiver.Here pass the

command to the Invoker.

Then, we simulate the button being pressed.

Page 209: Chapter 2

The Command Pattern DefinedThe Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.

execute ( ) { receiver.action ( ); }

action ()An encapsulated request

Command object encapsulates a request by binding together a set of actions on a specific receiver.To achieve this it packages the actions and the receiver up into an object that exposes just one method execute ( ).From the outside no other objects really know what actions get performed on what receiver. They just call the execute () to service their request!

Page 210: Chapter 2

The Command Pattern DefinedThe Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.

execute ( ) { receiver.action ( ); }

action ()An encapsulated request

We’ve seen a couple of examples of parameterizing an object with a command.The Waitress was parameterized with multiple orders throughout the day.In the simple remote control we can first load the button slot with a light on command and then later replace it with a open the garage door command.

Page 211: Chapter 2

The Command Pattern DefinedThe Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.

execute ( ) { receiver.action ( ); }

action ()An encapsulated request

Client Invoker

setCommand ( )

public void execute ( ) { receiver.action ( ) }

public void execute ( ) { receiver.action ( ) }

<< Interface >> Command execute ( ) undo ( )

Receiver action ( )

Concrete Command execute () undo ( )

Command declares an interface for all commands

Invoker holds a command and at some point asks the command to carry out a request by calling its execute ( ) method.

The client is responsible for creating a ConcreteCommand and setting its Receiver.

The Receiver knows how to perform the work needed to carry out any request. Any class can act as a Receiver.

Concrete Command defines a binding between an action and a Receiver. The Invoker makes a request by calling execute ( ) and the ConcreteCommand carries it out by calling one or more actions on the Receiver.

The execute method invokes the action(s) on the Receiver needed to fulfill request.

Page 212: Chapter 2

Implementing the RemoteControlpublic class RemoteControl { Command[] onCommands; Command[] offCommands; public RemoteControl() { onCommands = new Command[7]; offCommands = new Command[7]; Command noCommand = new NoCommand(); for (int i = 0; i < 7; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } } public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } public void onButtonWasPushed(int slot) { onCommands[slot].execute(); } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); } public String toString() { // code here }

This time around the remote is going to handle seven On and Off Commands which we will hold in the corresponding array.

In the constructor all we need to do is instantiate the on and off arrays.

The setCommand() method takes a slot position and an On and Off command to be stored in that slot. It puts these commands in the On and Off array for later use.

When an On or a Off button is pressed, the hardware takes care of calling the corresponding methods OnButtonWasPushed ( ) or OffButtonWasPushed ( ).

Used for testing.

Page 213: Chapter 2

Implementing the Commandspublic class LightOffCommand implements

Command { Light light; public LightOffCommand(Light light) { this.light = light; } public void execute() { light.off(); }}

public class StereoOnWithCDCommand implements Command {

Stereo stereo; public StereoOnWithCDCommand(Stereo

stereo) { this.stereo = stereo; } public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume(11); }}

The LightOffCommand works exactly like the LightOnCommand, except that we are binding the receiver to a different action: the off() command.

An instance of the stereo we are going to control is passed to constructor.

To carry out this request we need to call three methods on the stereo: first, turn it on, then set it to play the CD, and finally set the volume to 11 !

Page 214: Chapter 2

Testing the Codepublic class RemoteLoader { public static void main(String[] args) { RemoteControl remoteControl = new RemoteControl(); Light livingRoomLight = new Light("Living Room"); LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight); LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);

remoteControl.setCommand(0, livingRoomLightOn, livingRoomLightOff);

remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0);}

Create all the devices

Create all the Command objects

Load the command objects

Ready to roll! Test out the remote!

Page 215: Chapter 2

What is the NoCommand? In the remote control, we didn’t want to check to see if a

command was loaded for every slot. To do this we would need to do:

public void onButtonWasPushed (int slot) { if (onCommands[slot] != null ){ onCommands[slot].execute ( ); } }

To get around it, we introduce a new “NoCommand” object public class NoCommand implements Command { public void execute ( ) { }; }

Fixing the RemoteControl constructor: Command noCommand = new NoCommand ( ); for (int j=0; I < 7; j++ ){ onCommands[I] = noCommand; off Commands[I] = noCommand; }

NoCommand is an example of a null object. A null object is useful when you don’t have a meaningful object to return, yet you want to remove the responsibility for handling null from the client.

NoCommand is an example of a null object. A null object is useful when you don’t have a meaningful object to return, yet you want to remove the responsibility for handling null from the client.

Page 216: Chapter 2

Adding the Undo Feature

1. When commands support undo, they have an undo ( ) method that mirrors the execute ( ) method. Whatever execute ( ) last did, undo ( ) reverses it.

public interface Command { public void execute ( ); public void undo (); }

2. Implement the undo method in the LightOnCommand public class LightOnCommand implements Command {

public LightOnCommand (Light light){

this.light = light; } public void execute ( ) { light.on ( ); } public void undo ( ) { light.off ( ); } }

execute ( ) turns the light on so undo turns it off. Reverse for LightOffCommand.

Page 217: Chapter 2

Updating the RemoteControl class3. To add support for the undo button we only have to make a few small changes to

RemoteControl class

public class RemoteControl { Command[] onCommands; Command[] offCommands; Command undoCommand; public RemoteControl() { onCommands = new Command[7]; offCommands = new Command[7]; Command noCommand = new NoCommand(); for (int i = 0; i < 7; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } undoCommand = noCommand; }

This is where we will stash the last command executed for the undo button

Just like the other slots this is initialized to a NoCommand.

Page 218: Chapter 2

RemoteControl Classpublic void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } public void onButtonWasPushed(int slot) { onCommands[slot].execute(); undoCommand = onCommands[slot]; } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); undoCommand = onCommands[slot]; }

public void undoButtonWasPushed ( ) { undoCommand.undo ( ); } public String toString() { // code here }}

When the button is pressed we take the command and first execute it; then we save a reference to it in the undoCommand instance variable. We do this for both “on” and “off” commands.

When the undo button is pressed, we invoke the undo ( ) method of the command stored in the undoCommand. This reverses the operation that was last executed.

Page 219: Chapter 2

Using State to Implement Undopublic class CeilingFan { public static final int HIGH = 3; public static final int MEDIUM = 2; public static final int LOW = 1; public static final int OFF = 0; String location; int speed; public CeilingFan(String location) { this.location = location; speed = OFF; } public void high() { speed = HIGH; System.out.println(location + " ceiling fan is on high"); } public void medium() { speed = MEDIUM; System.out.println(location + " ceiling fan is on medium"); } public void low() { speed = LOW; System.out.println(location + " ceiling fan is on low"); }

public void off() { speed = OFF; System.out.println(location + " ceiling fan is off"); }

public int getSpeed() { return speed; } }

Holds local state

Set the speed of the ceiling fan.

Can get the current speed.

Page 220: Chapter 2

Adding Undo to Ceiling Fan Commandspublic class CeilingFanHighCommand implements Command { CeilingFan ceilingFan; int prevSpeed; public CeilingFanHighCommand(CeilingFan ceilingFan) { this.ceilingFan = ceilingFan; } public void execute() { prevSpeed = ceilingFan.getSpeed(); ceilingFan.high(); } public void undo() { if (prevSpeed == CeilingFan.HIGH) { ceilingFan.high(); } else if (prevSpeed == CeilingFan.MEDIUM) { ceilingFan.medium(); } else if (prevSpeed == CeilingFan.LOW) { ceilingFan.low(); } else if (prevSpeed == CeilingFan.OFF) { ceilingFan.off(); } }}

Added local state to keep track of the previous speed of the fan.

In execute ( ), before we change the speed we need to first record its previous state, just in case we need to undo our actions.

To undo, we set the speed of the fan back to its previous state.

Page 221: Chapter 2

The Party Mode

Executing multiple commands with one– Push one button to dim the lights, turn on the stereo and the

TV and set the to DVD. public class MacroCommand implements Command { Command[] commands; public MacroCommand (Command[ ] commands){ this.commands = commands; } public void execute ( ) { for (int j = 0; j < commands.length; j++){ commands[I].execute ( ); } }}

Take an array of Commands and store them in the MacroCommand

When the macro gets executed by the remote, execute those commands one at a time.

Page 222: Chapter 2

Using the Macro Command

1. Create the set of commands we want to go into the macro.

2. Create two arrays, one for the On Commands and the other for the Off Commands and load them with the corresponding commands.

3. Assign the macroCommand to the button as before.

4. Then push some buttons to test it out!

Page 223: Chapter 2

More Uses of the Command Pattern - Queuing Requests Commands provide a nice mechanism to package a piece of

computation (a receiver and a set of actions) and pass it around as a first-class object.

Imagine a job queue: – Add commands to the queue on one end, and on the other end sits a group of

threads– Threads run the following script:

• Remove command from the queue• Call its execute method• Wait for the call to finish• Discard the command object and retrieve the new one.

Here job queues are totally decoupled from the objects that are doing the computation - one minute the thread may be doing a financial computation and the next retrieving something from the network.

Page 224: Chapter 2

More Uses: Logging Requests

Semantics of some applications require that we log all actions and be able to recover after a crash by re-invoking those actions. The Command Pattern can store these semantics with the addition of two new methods: store ( ) and load ( ). – In Java we could use serialization to implement this.

How does it work?– As we execute commands, we store a history of them on disk

– When a crash occurs, we reload the command objects and invoke their execute () methods in batch and in order.

Page 225: Chapter 2

Summary

The Command pattern decouples an object making a request from one that knows how to perform it.

A Command object is at the center of this decoupling and encapsulates a receiver with an action (or set of actions)

An invoker makes a request of a Command object by calling its execute () method, which invokes those actions on the receiver.

Invokers can be parameterized with the Commands, even dynamically at runtime.

Commands may support undo by implementing an undo method that restores the object to its previous state before the execute ( ) method was last called.

Macro commands are a simple extension of Command that allow multiple commands to be invoked.

Commands may also be used to implement logging and transactional systems.

Page 226: Chapter 2

The Adapter Pattern

Putting a Square Peg in a Round Hole!

Page 227: Chapter 2

Wrapping Objects to Unify Interfaces

Question: What pattern wraps objects to give them new functionality?

Now we wrap objects with a different purpose:– To make their interfaces look like something they are not

– To simplify the interfaces of objects

Page 228: Chapter 2

Adapters

Real world is full of them!– Some examples?

Object oriented adapters– Scenario: you have an existing software system that you need to work a

new vendor library into, but the new vendor designed their interfaces differently than the last vendor.

– What to do? Write a class that adapts the new vendor interface into the one you’re expecting.

Your Existing System

Vendor Class

Their interface doesn’t match the one you’ve written your code against. Not going to work!

Your Existing System

Vendor Class

Adapter

The adapter implements the interface your classes expect

And talks to the vendor interface to service your requests

== Your Existing System

Vendor Class

Adapter

No code changes New code No code changes

Page 229: Chapter 2

If it walks like a duck…..

If it walks like a duck and quacks like a duck, then it might be a duck turkey wrapped with a duck adapter….

public interface Duck { public void quack (); public void fly (); } public class MallardDuck implements Duck { public void quack () { System.out.println(“Quack”); } public void fly ( ) { System.out.println (“I am flying”); } }

Meet the fowl!

public interface Turkey {

public void gobble (); public void fly ( ); } public class WildTurkey implements Turkey { public void gobble ( ) { System.out.println(“Gobble Gobble”); } public void fly ( ){ System.out.println(“I’m flying a short distance”); } }

Concrete implementations are similar -- just print out the actions.

Page 230: Chapter 2

Now….

Lets say you are short on Duck objects and would like to use some Turkey objects in their place.– Can’t use them outright because they have a different interface.

public class TurkeyAdapter implements Duck { Turkey turkey;

public TurkeyAdapter (Turkey turkey) {this.turkey = turkey;

}public void quack ( ) {

turkey.gobble ( );}public void fly ( ){

for (int j = 0; j<5; j++) turkey.fly ( );

} }}

First, you need to implement the interface of the type you are adapting to. This is the interface your client expects.

Next, we need to get a reference to the object that we are adapting; here we do that through the constructor.

Now we need to implement all the methods in the interface; the quack() translation between classes is easy; just call the gobble method.

Even though both interfaces have a fly ( ) method, Turkeys fly in short spurts -- they can’t do long distance flying like ducks. To map between a Duck’s fly ( ) method and a Turkey’s we need to call the Turkey’s fly ( ) method five times to make up for it.

Page 231: Chapter 2

The Adapter Pattern DefinedThe 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.

Client <<Interface>> Target request ( )

Adapter request ( )

Adaptee specificRequest ()

The client sees only the Target interface.

The Adapter implements the target interface

All requests get delegated to the AdapteeAdapter is composed with the Adaptee

Full of good OO design principles:--Use of object composition--Pattern binds the client to an interface and not an implementation

Full of good OO design principles:--Use of object composition--Pattern binds the client to an interface and not an implementation

Page 232: Chapter 2

Object and Class Adapters There are two types of Adapters

– Object Adapter : what we have seen so far.

– Class Adapter: not as common as it uses multiple inheritance, which isn’t possible in Java.

Client <<Interface>> Target request ( )

Adapter request ( )

Adaptee specificRequest ()

Difference: The only difference is that with class adapter we subclass the Target and the Adaptee, while the object adapter uses composition to pass requests to an adaptee.

Question: Object Adapters and Class Adapters use two different means of adapting the adaptee (composition versus inheritance). How do these implementations affect the flexibility of the adapter?

Page 233: Chapter 2

Real World Adapters Old world Enumerators

New world Iterators

And today…legacy code that exposes the Enumerator interface. Yet we want new code to use Iterators. Need an adapter.

<<interface>> Enumeration hasMoreElements ( ) nextElement ( )

<<interface>> Iterator hasNext ( ) next ( ) remove ( )

Enumeration has a simple interface.

Tells whether there are any more elements in the collection.

Returns the next element

Tells you if you have looked at all the elements

Gets the next one

Removes an item from the collection

Page 234: Chapter 2

Adapting an Enumeration to an Iterator First step: examine the two interfaces

<<interface>> Iterator hasNext ( ) next ( ) remove ( )

<<interface>> Enumeration hasMoreElements ( ) nextElement ( )

Target interfaceThese two methods look easy, they map straight to hasNext ( ) and next ( ) in Iterator

Adaptee interfaceBut what about this method remove ( ) in Iterator? There’s nothing like that in Enumeration.

Page 235: Chapter 2

Designing the Adapter

<<interface>> Iterator hasNext ( ) next ( ) remove ( )

EnumerationIterator hasNext ( ) next ( ) remove ( )

<<interface>> Enumeration hasMoreElements () nextElement ()

Your new code gets to use Iterators, even if there’s really an Enumeration underneath.

EnumerationIterator is the Adapter

We are making the Enumerations in your old code look like Iterators for your new code.

A class implementing the Enumeration interface is the adaptee.

Page 236: Chapter 2

Dealing with the remove ( ) method

Enumeration is a “read only” interface - it does not support the remove ( ) method.– Implies there is no real way to implement a fully functioning

remove () method.

– The best that can be done is to throw a runtime exception.

– Iterator designers foresaw the need and have implemented an UnsupportedOperationException.

Here the adapter is not perfect but is a reasonable solution as long as the client is careful and the adapter is well-documented.

Page 237: Chapter 2

EnumerationIterator - The Code public class EnumerationIterator implements Iterator { Enumeration enum; public EnumerationIterator (Enumeration enum) { this.enum = enum; }

public boolean hasNext () { return enum.hasMoreElements ( );}public Object next ( ) { return enum.nextElement ( );}

public void remove ( ) { throw new UnsupportedOperationException ( );}

}

Since we are adapting Enumeration to Iterator, the EnumerationIterator must implement the Iterator interface -- it has to look like the Iterator.

The Enumeration we are adapting. We’re using composition so we stash it in an instance variable.

hasNext ( ) and next () are implemented by delegating to the appropriate methods in the Enumeration.

For the remove ( ) we simply throw an exception.

Question: Some AC adapters do more than just change the interface -- they add other features like surge protection, indicator lights, and other bells and whistles.

If you were going to implement these kinds of features, what pattern would you use?

Page 238: Chapter 2

Summary

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

An adapter changes an interface into one a client expects. Implementing an adapter may require little work or a great deal of

work depending on the size and complexity of the target interface.

There are two forms of adapter patterns: object and class adapters. Class adapters require multiple inheritance.

An adapter wraps an object to change its interface, a decorator wraps an object to add new behaviors and responsibilities.

Page 239: Chapter 2

The Template Method Pattern

Encapsulating Algorithms

On an encapsulation role…encapsulated object creation, method invocation, complex interfaces, ducks, pizzas…and now we encapsulate pieces of algorithms!

Page 240: Chapter 2

Time for some more caffeine….

Starbuzz Coffee Barista Training Manual

Baristas! Please follow these recipes precisely when preparing Starbuzz beverages.

Starbuzz Coffee Recipe(1) Boil some water(2) Brew coffee in boiling water(3) Pour coffee in cup(4) Add sugar and milk

Starbuzz Tea Recipe(1) Boil some water(2) Steep tea in boiling water(3) Pour tea in cup(4) Add lemon

The recipe for coffee and tea are very similar!

Page 241: Chapter 2

Whipping up some Coffee in Java public class Coffee { void prepareRecipe ( ) {

boilWater ( ); brewCoffeeGrinds ( ); pourInCup ( ); addSugarAndMilk (); }

public void boilWater ( ) { System.out.println(“Boiling water”);}public void brewCoffeeGrinds ( ) {

System.out.println (“Dripping coffee thru filter”);}public void pourInCup ( ) {

System.out.println(“Pouring into cup”);}public void addSugarAndMilk ( ) {

System.out.println (“Adding Sugar and Milk” );}

}

Recipe for coffee - each step is implemented as a separate method.

Each of these methods implements one step of the algorithm. There’s a method to boil the water, brew the coffee, pour the coffee in the cup, and add sugar and milk.

Page 242: Chapter 2

And now for the Tea…. public class Tea { void prepareRecipe ( ) {

boilWater ( ); steepTeaBag ( ); pourInCup ( ); addLemon (); }

public void boilWater ( ) { System.out.println(“Boiling water”);}public void steepTeaBag ( ) {

System.out.println (“Steeping the Tea”);}public void pourInCup ( ) {

System.out.println(“Pouring into cup”);}public void addLemon ( ) {

System.out.println (“Adding Lemon” );}

}

Very similar to the coffee - 2nd and 4th steps are different.

These methods are exactly the same

These methods are specialized to Tea

We have code duplication - that’s a good sign that we need to clean up the design. We should abstract the commonality into a base class since coffee and tea are so similar, right?? -- Give a class diagram to show how you would redesign the classes.

Page 243: Chapter 2

Sir, may I abstract your Coffee, Tea?

CaffeineBeverage prepareRecipe ( ) boilWater ( ) pourInCup ( )

Coffee prepareRecipe ( ) brewCoffeeGrinds ( ) addSugarAndMilk ( )

Tea prepareRecipe ( ) steepTeaBag ( ) addLemon ( )

Is this a good redesign? Are we overlooking some other commonality? What are other ways that Coffee and Tea are similar?

The boilWater( ) and pourInCup ( ) are shared by both subclasses, so defined in the superclass.

The prepareRecipe ( ) method differs in each subclass, so it is defined as abstract.

Each subclass( ) overrides the prepareRecipe ( ) method and implements its own recipe.

The methods specific to Coffee and Teac stay in the subclasses.

Each subclass implements its own recipe.

Page 244: Chapter 2

What else do they have in common?

Both the recipes follow the same algorithm:

(1) Boil some water

(2) Use hot water to extract the tea or coffee

(3) Pour the resulting beverage into a cup

(4) Add the appropriate condiments to the beverage.

These two are already abstracted into the base class.

These aren’t abstracted but are the same, they just apply to different beverages.

Can we abstract prepareRecipe ( ) too? Yes…

Page 245: Chapter 2

Abstracting PrepareRecipe ( )

Provide a common interface for the different methods• Problem : Coffee uses brewCoffeeGrinds ( ) and

addSugarAndMilk () methods while Tea uses steepTeaBag ( ) and addLemon ( ) methods

• Steeping and brewing are pretty analogous -- so a common interface may be the ticket: brew ( ) and addCondiments ()

Page 246: Chapter 2

The New Java Classes….

public abstract class CaffeineBeverage {final void prepareRecipe ( ) {

boilWater ( );brew ( );pourInCup ( );addCondiments ( );

}abstract void brew ( );abstract void addCondiments ( );void boilWater ( ) {

System.out.println (“Boiling Water”);}void pourInCup ( ) {

System.out.println(“Pouring into cup”);}

}

Because Coffee and Tea handle these in different ways, they are going to have to be declared as abstract. Let the subclasses worry about that stuff!

public class Tea extends CaffeineBeverage {public void brew ( ){

System.out.println (“Steeping the Tes”);}public void addCondiments ( ) {

System.out.println(“Adding Lemon”);}

}

public class Coffee extends CaffeineBeverage {public void brew ( ) {

System.out.println (“Dripping Coffee Thru the Filters”);}public void addCondiments ( ){

System.out.println(“Adding Sugar and Milk”);}

}

Page 247: Chapter 2

What have we done?

We have recognized that the two recipes are essentially the same, although some of the steps require different implementations. – So we’ve generalized the recipe and placed it in the base class.

– We’ve made it so that some of the steps in the recipe rely on the subclass implementations.

Essentially - we have implemented the Template Method Pattern!

Page 248: Chapter 2

Meet the Template Method public abstract class CaffeineBeverage {

void final prepareRecipe ( ) {

boilWater ( );

brew ( );

pourInCup ( );

addCondiments ( );}

abstract void brew () ;abstract void addCondiments ( );

void boilWater () {// implementation

}

void pourInCup ( ) {// implementation

}}

prepareRecipe ( ) is the template method here. Why? Because: (1) it is a method (2) it serves as a template for an algorithm. In this case an algorithm for making caffeinated beverages.

In the template, each step of the algorithm is represented by a method.

Some methods are handled by this class….

….and some are handled by the subclass.

Methods that need to be supplied by the subclass are declared abstract.

The Template Method defines the steps of an algorithm and allows subclasses to provide the implementation of one or more steps.

Page 249: Chapter 2

Behind the scenes….. Tea myTea = new Tea ( ); myTea.prepareRecipe ( ); boilWater ( ); brew ( ); pourInCup ( ); addCondiments ( );

Polymorphism ensures that while the template controls everything, it still calls the right methods.

Page 250: Chapter 2

The Template Method DefinedThe Template Method Pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

AbstractClass templateMethod ( ) primitiveOperation1 ( ) primitiveOperation2 ( )

ConcreteClassprimitiveOperation1 ( ) primitiveOperation2 ( )

primitiveOperation1 (); primitiveOperation2 ();

The template method makes use of the primitiveOperations to implement an algorithm. It is decoupled from the actual implementations of these operations.

The ConcreteClass implements the abstract operations, which are called when the templateMethod ( ) needs them.

There may be many ConcreteClasses each implementing the full set of operations required by the template method.

….and abstract versions of the operations used in the template method.

The Abstract Class contains the template method.

Page 251: Chapter 2

Hooked on the Template Method A hook is a method that is declared in the abstract class, but only given an empty or

default implementation. – Gives the subclasses the ability to “hook into” the algorithm at various points, if they wish;

they can ignore the hook as well.

public abstract class CaffeineBeverageWithHook { void prepareRecipe ( ) {

boilWater ( );brew ( );pourInCup ( );if (customerWantsCondiments ( ) ){

addCondiments ( );}

}abstract void brew ( );abstract void addCondiments ( );

void boilWater ( ) {System.out.println(“Boiling Water”);

}void pourInCup ( ) {

System.out.println(“Pouring into cup”);}boolean customerWantsCondiments ( ){

return true;}

}

We’ve added a little conditional statement that bases its success on a concrete method, customerWantsCondiments ( ). If the customer WANTS condiments, only then do we call addCondiments ( )

This is a hook, because a subclass can override this method but doesn’t have to.

If subclasses want to use the hook they simply override it!

Page 252: Chapter 2

Low LevelComponent

Low LevelComponent

DP: The Hollywood Principle

The Hollywood Principle gives us a way to prevent “dependency rot”– Dependency rot happens when you have high-level components depending on low-

level components depending on high level components depending on sideways components depending on low level components and so on….

With the Hollywood principle – We allow low level components to hook themselves into a system

– But high level components determine when they are needed and how.

– High level components give the low-level components a “don’t call us, we’ll call you” treatment.

The Hollywood Principle: Don’t call us, we’ll call you!

But high-level components control when and how.

A low-level component never calls a high-level component directly.

Low-level components can participate in the computation.

High Level Component

Page 253: Chapter 2

The Hollywood Principle and the Template Method

CaffeineBeverage prepareRecipe ( ) boilWater ( ) pourInCup ( ) brew ( ) addCondiments ( )

Coffee brew ( ) addCondiments ( )

Tea brew ( ) addCondiments ( )

Clients of beverages will depend on the CaffeineBeverage abstraction rather than a concrete Tea or Coffee, which reduces dependencies in the overall system.

CaffeineBeverage is our high-level component. It has control over the algorithm for the recipe, and calls on the subclasses only when they are needed for an implementation of a method.

The subclasses are used simply to provide implementation details.

Tea and Coffee never call the abstract class directly without being “called” first.

What other patterns make use of the Hollywood Principle?

Page 254: Chapter 2

Template Methods in the Wild

Template method is a very common pattern and you’re going to find lots in the wild!

Some examples:– Sorting with Template Method– Swinging with Frames

Page 255: Chapter 2

Sorting with Template Method Arrays - common operation - sort them! Designers of Java Arrays provide a handy template method for sorting. (simplified version of how it works - look at actual source for more

details.)

public static void sort (Object[] a) { Object aux [ ] = (Object [])a.clone () ;

mergeSort (aux, a, 0, a.length, 0); }

private static void mergeSort (Object [] src, Object [] dest, int low, int high, int off) {for (int I = low; I < high; I++ ) {

for (int j = I; j > low && ((Comparable)dest[j-1].compareTo((Comparable)dest[j]) > 0; j--) { swap (dest, j, j-1);

}}return;

}

The method sort () is a helper method that creates a copy of the array and passes it along as the destination array to the mergeSort ( ). It also passes along the length of the array and tells the sort to start at the first element.

The mergeSort () method contains the sort algorithm, and relies on an implementation of the compareTo ( ) method to complete the algorithm. Check out the actual src code for the nitty gritty details.

Think of this as the template method

compareTo ( ) is the method we need to implement to “fill out” the template method.

This is a concrete method already defined in the Arrays class.

Page 256: Chapter 2

Sorting some Ducks… Assume that you have an array of ducks to sort. How would you

do it? Use the sort ( ) template method in the Array to do the sort

– Need to implement the compareTo ( ) method -- to tell the sort ( ) how to compare ducks.

Any issues here?

In the Template method we typically would subclass something. An array doesn’t subclass anything. Reason: The designers of sort ( ) wanted it to be useful across all arrays, so they had to make sort ( ) a static method that could be used from anywhere. One more detail - because we are not using subclassing, the sort ( ) method needs to know that you have implemented the compareTo ( ) method. To handle this there is the Comparable interface that your class needs to implement. It has just one method - compareTo().

Page 257: Chapter 2

Comparing Ducks and Ducks public class Duck implements Comparable {

String name;int weight;public Duck (String name, int weight) {

this.name = name;this.weight = weight;

}public String toString ( ){

return name + “ weighs “ + weight;}

public int compareTo ( Object object ) {Duck otherDuck = (Duck) object;if (this.weight < otherDuck.weight) {

return -1;} else if (this.weight ==

otherDuck.weight) {return 0;

} else { //this.weight > otherDuck.weight

return 1;}

}}

public class DuckSortTestDrive {public static void main (String[] args){

Duck [ ] ducks = { new Duck (“Daffy”, 8),new Duck (“Dewey”, 2),new Duck (“Howard”, 7),new Duck (“Louie”, 2),new Duck (“Donald”, 10),new Duck (“Huey”, 2) };

System.out.println(“Before sorting”);display(ducks);

Arrays.sort (ducks);

System.out.println(“\n After Sorting”);display (ducks);

}public static void display (Duck[] ducks){

for (int j=0; j < ducks.length; j++) System.out.println(ducks[j]);

}}

Page 258: Chapter 2

Is this really a Template Method Pattern? The pattern calls for implementing an algorithm, and letting

subclasses supply the implementation of the steps. Array.sort ( ) is doing just that! Patterns in real life are often adaptations of the book patterns Designers of the Arrays sort ( ) method had some constraints:

– In general you can’t subclass Java Array and they wanted sort to be useful for all arrays

– For Array sort ( ) implementation:• static method was defined

• Comparison was deferred to the items being sorted.

– So yes this is a Template Method!

Page 259: Chapter 2

Swingin’ with Frames

JFrame - most basic Swing container and inherits a paint ( ) method. Default behavior of paint ( ) method - does nothing because it is a hook. By overriding the paint () method, you can insert yourself into JFrame’s

algorithm for displaying its area of screen and have your own graphic output incorporated into the JFrame.

Next up -- a simple example using JFrame to override the paint ( ) method.

Page 260: Chapter 2

Simple JFrame Example public class MyFrame extends JFrame {

public MyFrame (String title) {super (title);this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

this.setSize ( 300, 300);this.setVisible (true);

}public void paint (Graphics graphics){

super.paint (graphics);String msg = “I rule!!”;graphics.drawString(msg, 100, 100);

}public static void main (String[] args){

MyFrame myFrame = new MyFrame (“Head First Design Patterns”);}

}

We’re extending JFrame, which contains a method update () that controls the algorithm for updating the screen. We can hook into that algorithm by overriding the paint () method.

Don’t look behind the curtain, just some initialization here….

JFrame’s update algorithm calls paint ( ). By default paint() does nothing…it’s a hook. We are overriding paint(), and telling the JFrame to draw a message in the window.

Page 261: Chapter 2

Applets Applets provide numerous hooks!

public class MyApplet extends Applet {

String message;

public void init ( ){message = “Hello World, I’m alive!”;repaint ( );}public void start ( ){message = “Now I’m starting up…”;repaint ( );}public void stop ( ) {message = “Now I’m being stopped…”;repaint ();}public void destroy ( ){// applet is going away}public void paint (Graphics g){g.drawString(message, 5, 15);}

}

The init hook allows the applet to do whatever it wants to initialize the applet the first time.

repaint ( ) is a concrete method in the Applet class that lets upper-level components know that the applet needs to be redrawn.

The start hook allows the applet to do something when the applet is just about to be displayed on the web page.

If the user goes to another page, the stop hook is used and the applet can do whatever it needs to do to stop its actions.

And the destroy hook is used when the applet is going to be destroyed, say, when the browser pane is closed. We could try and display something here…but what’s the point?

Well looky here! Applet also makes use of the paint() method as a hook.

Concrete applets make extensive use of hooks to supply their own behaviors. Because these methods are implemented as hooks, the applet isn’t required to implement them.

Page 262: Chapter 2

Summary (1/2)

A “template method” defines the steps of an algorithm, deferring to subclasses for the implementation of those steps.

The Template Method Pattern gives us an important technique for code reuse.

The template method’s abstract class may define concrete methods, abstract methods and hooks.

Abstract methods are implemented by subclasses. Hooks are methods that do nothing or default behavior in the

abstract class, but may be overridden in the subclasses. To prevent the subclasses from changing the algorithm in the

template method, declare the template method as final.

Page 263: Chapter 2

Summary (2/2)

The Hollywood Principle guides us to put decision making in high level modules that can decide how and when to call the low-level modules.

You’ll see lots of uses of the Template Method Pattern in real world code, but don’t expect it all (like any pattern) to be designed “by the book”.

The Factory Method is a specialization of the Template Method!

Page 264: Chapter 2

The Iterator and Composite Patterns

Well-Managed Collections!

Page 265: Chapter 2

Breaking news….. The Objectville Diner and Pancake House have merged! Menus

must be merged and have their separate identities! Owners agree on the implementation of the MenuItems.

public class MenuItem {

String name;String description;boolean vegetarian;double price;public MenuItem (String name,

String description, boolean vegetarian,double price ) {

// code here}// set of getter methods to get access to the fields.

}

Page 266: Chapter 2

Menu Implementations - Pancake House public class PancakeHouseMenu {

ArrayList menuItems;public PancakeHouseMenu ( ) { menuItems = new ArrayList ();

addItem (“Regular Pancake Breakfast”, “Pancakes with fried eggs, sausage”, false, 2.99);addItem (“Blueberry pancakes”,

“Pancakes made with fresh blueberries, true, 3.49); //other items}public void addItem (String name, String description,

boolean vegetarian, double price) {MenuItem menuItem = new MenuItem (name, description,

vegetarian, price);menuItems.add(menuItem);

}public ArrayList getMenuItems ( ) {

return menuItems;}// other methods

}

Uses an ArrayList, so the menu can be easily expanded.

To add a menuItem -- create a MenuItem object, add it to the arrayList

Page 267: Chapter 2

Menu Implementation - Diner public class DinerMenu {

static final int MAX_ITEMS = 6;MenuItem[] menuItems;int numberOfItems = 0;

public DinerMenu ( ) { menuItems = new MenuItem[MAX_ITEMS];

addItem (“Vegetarian BLT”, “(Fakin’) Bacon with Lettuce & tomato on whole wheat”, true, 2.99);addItem (“Soup of the Day”, “Soup of the Day, with a side of potato salad”, false, 3.29);

// other items}public void addItem (String name, String description, boolean vegetarian, double price) {

MenuItem menuItem = new MenuItem (name, description, vegetarian, price);if (numberOfItems >= MAX_ITEMS){

System.err.println(“Sorry menu is full! Can’t add any more items”);}else {

menuItems[numerOfItems] = menuItem;numberOfItems = numberOfItems + 1;

}}public MenuItem[] getMenuItems ( ) {

return menuItems;}// other methods

}

Uses an Array: max size can be controlled no casting is needed

To add a menuItem -- create a MenuItem object, add it to the array if the max size has not been exceeded.

Page 268: Chapter 2

What’s the problem with having two different menu representations? What would it take to implement the functionality that a Java-

enabled Waitress may want:

– printMenu ( ): prints every item on the menu

– printBreakfastMenu (): prints just the breakfast items

– printLunchMenu ( ): prints just the lunch items

– printVegetarianMenu (): prints all the vegetarian items

– isItemVegetarian(name): given the name of the item, returns true if vegetarian, false otherwise

Page 269: Chapter 2

Implementing the Waitress1. To print all the items on each menu: PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu ( ); ArrayList breakfastItems = pancakeHouseMenu.getMenuItems ();

DinerMenu dinerMenu = new DinerMenu (); MenuItem[] lunchItems = dinerMenu.getMenuItems ( );

2. Print the items from the PancakeHouseMenu and the DinerHouseMenu -- need to loop over the ArrayList and Array respectively.

for (int j = 0; j < breakfastItems.size(); j++){

MenuItem menuItem = (MenuItem)breakfastItems.get(j);System.out.println(menuItem.getName ( ));// print out the description, vegetarian, and price

} for (int j = 0; j < lunchItems.length; j++) {

MenuItem menuItem = lunchItems[j];

3. Implementing the other methods is a variation on this theme. If another restaurant is added in, we would need three loops!

The methods look the same, but return different types -- ArrayList versus Array

Page 270: Chapter 2

What now?

Implementations can not be modified– Requires rewriting a lot of code in each respective

menu

Need: same interface for menus– getMenuItems() need to return a common object

type

How do we do that?

Page 271: Chapter 2

What now?

One of the key principles is : encapsulate what varies. What varies here?

Iteration caused by different collections of objects returned from the menus.

Can we encapsulate this?1. To iterate through the breakfast items we use size() and get () methods on

the Arraylist.2. To iterate through the lunch items we use the Array length field and the array

subscript notation on MenuItem Array.

Page 272: Chapter 2

Simple Iterator What if we create an object , an Iterator, that encapsulates how we iterate

through a collection of objects.

Iterator iterator = breakfastMenu.createIterator ( ); while (iterator.hasNext ( )) { MenuItem menuItem = (MenuItem)iterator.next (); }

Similarly,

Iterator iterator = lunchMenu.createIterator ( ); while (iterator.hasNext ( )){ MenuItem menuItem = (MenuItem)iterator.hasNext ( );

Page 273: Chapter 2

Meet the Iterator Pattern

The Iterator Design Pattern relies on an interface called the Iterator interface.

<<interface>> Iterator hasNext ( ) next ( )

A possible Iterator interface

Page 274: Chapter 2

Using the Iterator for the Diner Menu public interface Iterator {

boolean hasNext ( );Object next ( );

} // a concrete iterator public class DinerMenuIterator implements Iterator {

MenuItem[] items;int position = 0;

public DinerMenuIterator (MenuItem[] items) {this.items = items;

}public Object next ( ) {

MenuItem menuItem = item[position];position = position + 1;return menuItem;

}public boolean hasNext ( ) {

if (position >= items.length || items[position] == null) {return false;

} else {return true;

}}

}

We implement the Iterator interface

Position maintains the current position of the iteration over the array.

The constructor takes the array of menu items we are going to iterate over.

The next ( ) method returns the next item in the array and increments the position.

The hasNext () method checks to see if we’ve seen all the elements of the array and returns true if there are more to iterate over.

Because the Diner chef went ahead and allocated a max sized array, we need to check not only if we are at the end of the array, but also if the next item is null which indicates there are no more items.

Page 275: Chapter 2

Reworking the Diner Menu with Iterator public class DinerMenu {

static final int MAX_ITEMS = 6;int numberOfItems = 0;MenuItem[] menuItems ;

// constructor here

// addItem here

public MenuItem[] getMenuItems ( ) {return menuItems;

}

public Iterator createIterator ( ){return new DinerMenuIterator (menuItems);

}// other menu methods here

}

We’re not going to need the getMenuItems() method anymore and in fact we don’t want it because it exposes our internal implementation!

Here’s the createIterator () method. It creates a DinerMenuIterator from the menuItems array and returns it to the client.

We’re returning the Iterator interface. The client doesn’t need to know how the menuItems are maintained in the DinerMenu, nor does it need to know how the DinerMenuIterator is implemented. It just needs to use the iterators to step through the items in the menu.

Page 276: Chapter 2

Fixing up the Waitress Code public class Waitress {

PancakeHouseMenu pancakeHouseMenu;DinerMenu dinerMenu;

public Waitress (PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {this.pancakeHouseMenu = pancakeHouseMenu;this.dinerMenu = dinerMenu;

}

public void printMenu ( ){Iterator dinerIterator = dinerMenu.createIterator ( );System.out.println(“\nLunch”);printMenu (dinerIterator);// similar set of statements for Breakfast menu

}

public void printMenu (Iterator iterator) {while (iterator.hasNext ( )) {

MenuItem menuItem = (MenuItem)iterator.next ( );// print it out

}}

}

Waitress takes the two objects as before

The printMenu ( ) creates two iterators one for each menu

Back to one loop! Here is where the printing occurs.

Page 277: Chapter 2

What have we done? The Menus are not well

encapsulated; we can see the Diner is using an ArrayList and the Pancake House an Array.

We need two loops to iterate through the MenuItems.

The Waitress is bound to concrete classes (MenuItem[] and ArrayList)

The Waitress is bound to two concrete Menu classes, despite their interfaces being almost identical.

The Menu implementations are now encapsulated. The Waitress has no idea how the Menus hold their collection of menu items.

All we need is a loop that polymorphically handles any collection of items as long as it implements the iterator.

The Waitress now uses an interface (Iterator).

The Menu interfaces are now exactly the same and uh, oh, we still don’t have a common interface, which means the Waitress is still bound to two concrete Menu classes.

Page 278: Chapter 2

Bird’s Eye View of Current Design

WaitressprintMenu ( )

PancakeHouseMenu

menuItems createIterator ( )

DinerMenu menuItems createIterator ( )

<<interface>> Iterator hasNext ( ) next ( )

PancakeHouseMenuIterator hasNext ( ) next ( )

DinerMenuIterator hasNext ( ) next ( )

The Iterator allows the Waitress to be decoupled from the actual implementation of the concrete classes. She doesnot need to know if a Menu is implemented with an Array or ArrayList or with PostIt notes! All she cares is that she can get an iterator to do her iterating.

Note that the iterator gives us a way to step through the elements of an aggregate without having the aggregate clutter its own interface with a bunch of methods to support traversal of its elements. It also allows the implementation of the iterator to live outside the aggregate --- in other words, we ‘ve encapsulated the iteration.

The waitress is still bound to two concrete Menu classesSolution: define a common interface for the PancakeHouseMenu and DinerMenu!

Page 279: Chapter 2

The Iterator Pattern DefinedThe Iterator Pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying implementation.

The Iterator places the task of traversal on the iterator object, not on the aggregate, which simplifies the aggregate interface and implementation, and places the responsibility where it should be.

<<interface>> Aggregate createIterator ( )

ConcreteAggregate createIterator ( )

<<interface>> Iterator hasNext ( ) next ( ) remove ( )

ConcreteIterator hasNext ( ) next ( ) remove ( )

Client

Page 280: Chapter 2

DP: Single Responsibility

Every responsibility of a class is an area of potential change. More than one responsibility means more than one area of change.

This principle guides us to keep each class to a single responsibility.

We have studied the principle of single responsibility at the module level. What is it?

DP: A class should have only one reason to change.

Page 281: Chapter 2

The java.util.Iterator

The java.util.Iterator interface supports the Iterator pattern that we have discussed thus far.

The Java Collections Framework -- provides a set of classes and interfaces, including ArrayList, Vector, LinkedList, Stack and PriorityQueue.

All of these classes implement the Collections interface, and provide a method iterator () to return an instance of the java.util.iterator to iterate over the collection.

Page 282: Chapter 2

Using java.util.Iterator

WaitressprintMenu ( )

PancakeHouseMenu

menuItems createIterator ( )

DinerMenu menuItems createIterator ( )

<<interface>> Iterator hasNext ( ) next ( )

PancakeHouseMenuIterator hasNext ( ) next ( )

DinerMenuIterator hasNext ( ) next ( )

<<interface>> Menu createIterator ()

These now implement the Menu interface which means they need to implement the createIterator ( ) method.

We’re now using the ArrayList iterator supplied by java.util. We don’t need this anymore

DinerMenu returns a DinerMenuIterator from its createIterator() method because that’s the kind of iterator required to iterate over its Array of menu items.

Each concrete Menu is responsible for creating the appropriate concrete Iterator class -- java.util.Iterator or DinerMenuIterator.

The Waitress is decoupled from the implementation of the menus, so now we can use an Iterator to iterate over any list of menu items without having to know about how the list of items is implemented.

Page 283: Chapter 2

Iterator in Java 5 Iterators and Collections in Java 5:

– Added support for iterating over Collections so that you don’t even have to ask for an iterator!

Includes a new form of for statement -- for/in– Lets you iterate over a collection or an array without creating an iterator

explicitly.

for (Object obj: collection) {

…… }

ArrayList items = new ArrayList ( ); items.add(new MenuItem(“Pancakes”, “delicious pancakes”, true, 1.59); items.add(new MenuItem(“Waffles”, “yummy waffles”, true, 1.99); items.add(new MenuItem(“Toast”, “perfect toast”, true, 0.59);

for (MenuItem item: items) { System.out.println(“Breakfast item: “ + item); }

Page 284: Chapter 2

Is the Waitress ready for prime time? public void printMenu ( ){ Iterator pancakeIterator = pancakeHouseMenu.createIterator ( );

Iterator dinerIterator = dinerMenu.createIterator ( );Iterator cafeIterator = cafeMenu.createIterator ( );

System.out.println (“MENU\n-------\nBREAKFAST”);printMenu(pancakeIterator);

System.out.println(“\nLUNCH”);printMenu(dinerIterator);

System.out.println(“\nDINNER”);printMenu(cafeIterator);

} void printMenu (Iterator iterator) {

// iterate over the collection and print }

Whats wrong with this?We have done a good job of decoupling the menu implementation and extracting the iteration into an iterator. But we are still handling the menus with separate, independent objects --- we need a way to manage them together. Ideas?

Page 285: Chapter 2

Packaging into an ArrayList We could package the menus up into an ArrayList and then get its iterator to

iterate through each Menu. The code in the Waitress should be simpler and it could handle any number of menus.

public class Waitress {

ArrayList menus;public Waitress (ArrayList menus) {

this.menus = menus;}public void printMenu ( ) {

Iterator menuIterator = menus.iterator ( );while (menuIterator.hasNext ( )){

Menu menu = (Menu)menuIterator.next ( );printMenu (menu.createIterator());

}}

void printMenu (Iterator iterator) {

// no code changes here}

We do loose the name of the menus in this implementation.

Page 286: Chapter 2

Just when we thought it was safe … The Diner wants to add a new dessert “submenu” What does that mean?

– We have to support not only multiple menus, but menus within menus. Solutions: we could make the Dessert menu an element of the DinerMenu collection, but that won’t

work as it is now implemented.– DessertMenu will need to be implemented as a collection– We can’t actually assign a menu to a MenuItem array because the types are different.

Time for a change!

Page 287: Chapter 2

So what do we need?

We need some kind of a tree shaped structure that will accommodate menus, submenus, and menu items

We need to make sure we maintain a way to traverse the items in each menu that is at least as convenient as what we are doing now with iterators

We need to be able to traverse the items in a more flexible manner. – For instance, we might need to iterate over only the Diner’s

dessert menu, or we might need to iterate over the Diner’s entire menu, including the dessert menu.

Page 288: Chapter 2

Possibilities

All Menus

PancakeHouseMenu

DinerMenu

DessertMenu

MenuItems

Menus and submenus sub-structure naturally fit into a tree-like structure

Can accommodate menus, submenus and menuitems

Page 289: Chapter 2

The Composite Pattern DefinedThe Composite Pattern allows you to compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and composition of objects uniformly.

1. We can create arbitrarily complex trees.

2. We can treat them as a whole or as parts

3. Operations can be applied to the whole or the part.

leaf

node

Page 290: Chapter 2

Composite Pattern Structure

Component operation ( ) add (Component) remove (Component) getChild (int)

Composite operation ( ) add(Component) remove (Component) getChild (int)

Leaf operation ( )

Client

The client uses the Component interface to manipulate the objects in the composition.

The Component defines an interface for all objects in the composition: both the composite and the leaf nodes.

The Component may implement a default behavior for add ( ), remove (), getChild() and its operations.

Note that the leaf also inherits methods like add(), remove(), and getChild(), which don’t make a lot of sense for a leaf node. We will come back to this issue!

A leaf has no children

A Leaf defines the behavior for the elements in the composition. It does this by implementing the operations the Composite supports. The Composite’s role is to define

the behavior of the components having children and to store child components

The Composite also implements the Leaf-related operations. Note that some of these may not make sense on a Composite so in that case an exception might be generated.

Page 291: Chapter 2

Designing Menus with Composite

MenuItem getName ( ) getDescription ( ) getPrice ( ) isVegetarian ( ) print ( )

Menu menuComponents getName ( ) getDescription ( ) print ( ) add (Component) remove(Component) getChild (int)

MenuComponent getName () getDescription () getPrice () isVegetarian () print ( ) add(Component) remove(Component) getChild (int)

Waitress

The Waitress is going to use the MenuComponent interface to access both Menus and MenuItems.

Here are the methods for manipulating the components: Menu and MenuItem.

Both MenuItem and Menu override the print() method.

MenuItem overrides the methods that make sense, and uses the default implementations (Unsupported Exception, for example) in MenuComponent for those that don’t make sense (like add())

MenuComponent represents the interface for both MenuItem and Menu. We’ve used an abstract class here because we want to provide default implementations for these methods.

We have some of the same methods from our previous versions of MenuItem and Menu, and we’ve added the print()

Menu also overrides the methods that make sense, like a way to add and remove menu items (and submenus!) from the menuComponents. In addition, we can use getName() and getDescription() methods to return the name and description of the menu.

Page 292: Chapter 2

An Observation First we say: One Class, One Responsibility. Composite is a pattern with two responsibilities in one class:

manages a hierarchy and it performs operations related to Menus.

In the Composite pattern we trade the Single Responsibility design principle for transparency.– The client can treat both composites and leaf nodes uniformly

We lose: safety because the client may try to do something inappropriate or meaningless.– We could take the design in the other direction and separate out the

responsibilities into interfaces. This could make the design safe.– We would loose transparency in this case and our code would have to use

conditionals and the instanceOf operator.

Page 293: Chapter 2

Flashback to the Iterator - A Composite Iterator To implement a Composite Iterator we add the createIterator () method in

every component. – We add a createIterator () method to the abstract MenuComponent. This

means that each Menu and MenuItem will need to implement this method. It also means that calling createIterator() on a composite should apply to all children of the composite.

Implementations in Menu and MenuItem:

public class Menu extends MenuComponent {

// other code does not change public Iterator createIterator ( ) {

return new CompositeIterator (menuComponents.iterator ( ));}

} public class MenuItem extends MenuComponent {

// other code does not changepublic Iterator createIterator ( ) {

return new NullIterator ( );}

}

Here we’re using a new iterator called CompositeIterator. It knows how to iterate over any composite. We pass it the current composite’s iterator.

NullIterator coming up….

Page 294: Chapter 2

The Composite Iterator - A Serious Iterator import java.util.*; public class CompositeIterator implements Iterator {

Stack stack = new Stack ( );public CompositeIterator (Iterator iterator) {stack.push(iterator);

}public Object next ( ) {if (hasNext ( )){Iterator iterator = (Iterator) stack.peek();MenuComponent component = (MenuComponent) iterator.next ( );if (component instanceOf Menu) {stack.push (component.createIterator());}return component;} else {return null;} }public boolean hasNext ( ) {if (stack.empty()) {return false;} else {Iterator iterator = (Iterator) stack.peek ( );if (!iterator.hasNext ( )) {stack.pop();return hasNext ( );} else {return true;} } }public void remove ( ){throw new UnsupportedOperationException () ;}

}

Like all iterators, we’re implementing the java.util.Iterator interface.

The iterator of the top level composite we’re going to iterate over is passed in. We throw that in a stack data structure.

When the client wants the next element we first make sure there is one by calling hasNext ( )

If there is a next element, we get the current iterator off the stack and get its next element.

If that element is a menu, we have another composite that needs to be included in the iteration, so we throw it on the stack. In either case, we return the component.

To see if there is a next element, we check to see if the stack is empty;

Otherwise, we get the iterator off the top of the stack and see if it has a next element. If it doesnot we pop it off the stack and call hasNext ( ) recursively.

We are not supporting remove, just traversal.

Page 295: Chapter 2

The Null Iterator A MenuItem has nothing to iterate over. So how do we handle the

createIterator () implementation?–Choice 1: return null

• We could return null, and have conditional code in the client to check if a null was returned or not.

–Choice 2: • Return an iterator that always returns a false when hasNext ( ) is called. ---

create an iterator that is a no-op.

public class NullIterator implements Iterator {public Object next () {

return null; }

public boolean hasNext ( ) { return false;

}public void remove () {

throw new UnsupportedOperationException ();}

}

Page 296: Chapter 2

Give me the vegetarian menu… public class Waitress {

MenuComponent allMenus;public Waitress (MenuComponent allMenus) {

this.allMenus = allMenus;}public void printMenu ( ){

all.Menus.print ();}public void printVegetarianMenu ( ) {

Iterator iterator = allMenus.createIterator ( );System.out.println(“\n VEGETARIAN MENU\n-----”);while (iterator.hasNext ( )) {

MenuComponent menuComponent = (MenuComponent) iterator.next ( );try {

if (menuComponent.isVegetarian()) {menuComponent.print();

}catch (UnsupportedOperationException e) { }

}}

}

print() is only called on MenuItems, never on composites. Can you see why?

We implemented isVegetarian() on the Menus to always throw an exception. If that happens we catch the exception, but continue with the iteration….

The printVegetarianMenu ( ) method takes the allMenu’s composite and gets its iterator. This will be our CompositeIterator.

Page 297: Chapter 2

Exceptions and Program Logic…. In general, using exceptions to implement program logic is a big no, no!

– Yet that’s exactly what we are doing with the isVegetarian() method. We could have checked the runtime type of the Menu component with

instanceOf to make sure it’s a MenuItem before making the call to isVegetarian(). But in the process we would lose transparency.

We could also change isVegetarian() in the Menus to return a false. This provides a simple solution and we keep our transparency.

We choose to go for clarity - we want to communicate that for the Menus this really is an unsupported operation. It also allows for someone to come along and implement a reasonable isVegetarian ( ) method for Menu and have it work with existing code.

Page 298: Chapter 2

Summary (1/2)

An iterator allow access to an aggregate’s elements without exposing its internal structure.

An iterator takes the job of iterating over an aggregate and encapsulates it in another object.

When using an iterator, we relieve the aggregate of the responsibility of supporting operations for traversing its data.

An iterator provides a common interface for traversing the items of an aggregate, allowing us to use polymorphism when writing code that makes use of the items of the aggregate.

We should strive to assign only one responsibility to each class.

Page 299: Chapter 2

Summary (2/2)

The Composite Pattern provides a structure to hold both the individual objects and composites.

The Composite Pattern allows clients to treat composites and individual objects uniformly.

A Component is any object in a composite structure. Components may be other composites or leaf nodes.

There are many design tradeoffs in implementing the Composite. You need to balance transparency and safety with your needs.

Page 300: Chapter 2

The King of Compound Patterns

Page 301: Chapter 2

Meet the Model-View-Controller

Picture your favorite MP3 player– You can use its interface to add new songs, manage

play lists and rename tracks– The player maintains

• Database of all your songs along with associated names and data.

• Plays the song• Updates the interface constantly with current song, running

time and so on

Underneath the covers --- Model View Controller

Page 302: Chapter 2

Model View Controller

class Player { play ( ) { } rip ( ) { } burn ( ) { } }

Controller

Model

View

You use the interface and your actions go to the controller

“ Play new song”

Controller manipulates the model

Controller asks Player model to begin playing the song

Model tells the view the state has changed

The model notifies the view of a change in its state.

You see the song display update and hear the new song playing

The view display is updated for you.

The model contains all the state, data, and application logic needed to maintain and play mp3s.

Page 303: Chapter 2

A Closer Look…. Lets see the nitty gritty details of how this MVC pattern works….

– Step through the relationships among the model

– Take a look from Design pattern perspective.

class Player { play ( ) { } rip ( ) { } burn ( ) { } }

Controller

Model View

VIEW:Gives you a presentation of the model. The view usually gets the state and data it needs to display directly from the model.

CONTROLLER:Takes user input and figures out what it means to the model.

MODEL:The model holds all the data, state and application logic. The model is oblivious to the view and controller, although it provides an interface to manipulate and retrieve its state and it can send notifications of state changes to the Observer.

(1) The user did something

(2) Change your state

(3) Change your display

(4) I have changed

(5) I need your state information Here’s the model; it handles all application data and logic.

This is the user interface

Here’s the creamy controller; it lives in the middle.

Page 304: Chapter 2

A Closer Closer Look….(1) You are the user -- you interact with the view

– The view is your window to the model. When you do something to the view (like click the Play button), then the view tells the controller what you did. It’s the controller’s job to handle that.

(2) The controller asks the model to change its state– The controller takes your actions and interprets them. If you click on a button, it’s the controller’s job

to figure out what that means and how the model should be manipulated based on that action.

(3) The controller may also ask the view to change– When the controller receives an action from the view, it may need to tell the view to change as a result.

For example, the controller could enable or disable certain buttons or menu items in the interface.

(4) The model notifies the view when its state has changed.– When something changes in the model, based on either some action you took (like clicking a button) or

some other internal change (like the next song in the playlist has started), the model notifies the view that its state has changed.

(5) The view asks the model for state– The view gets the state it displays directly from the model. For instance, when the model notifies the

view that a new song has started playing, the view requests the song name from the model and displays it. The view might also ask the model for state as the result of the controller requesting some change in the view.

Page 305: Chapter 2

Looking at MVC through patterns-colored glasses MVC is set of patterns together in the same design. Model uses Observer to keep views and controllers

updated on the latest state changes. View and Controller implement a Strategy Pattern

– Example: Controller is the behavior of the view and can be easily exchanged with another controller if you want different behavior.

View also uses a pattern internally to manage the windows buttons and other components of the display => the Composite Pattern

Page 306: Chapter 2

A Closer Look….

class Player { play ( ) { } rip ( ) { } burn ( ) { } }

Controller

Model

View

(1) The user did something

(2) Change your state

(3) Change your display

(4) I have changed

(5) I need your state information

Strategy:The View and the Controller implement the classic Strategy Pattern: the view is an object that is configured with a strategy. The view is concerned only with the visual aspects of the application, and delegates to the controller for any decisions about the interface behavior. Using the Strategy pattern also keeps the view decoupled from the model, because it is the controller that is responsible for interacting with the model to carry out user requests. The view knows nothing about how it gets done.

The display consists of a nested set of windows, panels, buttons, text labels and so on. Each display component is a composite (like a window) or a leaf (button). When the controller tells the view to update, it only has to tell the top view component, and the Composite takes care of the rest.

The model implements the Observer Pattern to keep the interested objects updated when the state changes occur. Using the Observer Pattern keeps the model completely independent of the views and the controllers. Its allows us to use different views with the same model, or even multiple views at once.

Page 307: Chapter 2

Observer

My state has changedObservable

Model

View

I’d like to register as an observer

Any object that’s interested in state changes in the model registers with the model as an observer.

Observers

All these observers will be notified whenever state changes in the model.

View

Model

Controller

The model has no dependencies on viewers or controllers!

class Foo { void bar ( ) { doBar(); } }

Page 308: Chapter 2

Strategy

The user did something

View

Controller

Controller

The view delegates to the controller to handle the user actions.

The controller is the strategy for the view -- it’s the object that knows how to handle the user actions.

We can swap another behavior for the view by changing the controller.The view only worries about presentation, the controller worries

about translating user input to actions on the model.

Page 309: Chapter 2

Composite

View

Window

Set BPM

Set<< >>

paint ()

The view is a composite of GUI components (labels, buttons, text entry, etc.). The top level component contains other components, which contain other components, and so on until you get to the leaf nodes.

Page 310: Chapter 2

Using MVC to control the beat…

Time to be a DJ and start mixing with a beat! The Java DJ view:

View

Current BPM: 120

A pulsing bar shows the beat in real time

A display shows the current BPMs and is automatically set whenever the BPM changes.

120

Control

Enter BPM

Set<< >>

You can enter a specific BPM and click the Set button to set a specific beats per minute, or you can use the increase and decrease buttons for fine tuning.

The view has two parts, the part for viewing the state of the model and the part for controlling things.

Decreases the BPM by one beat per minute. Increases the BPM by one beat per minute.

Page 311: Chapter 2

The Controller is in the middle…

The controller sits between the view and the model. It takes your input, like decreasing the BPM and turns it into an action on the model to decrease the BPM.

Page 312: Chapter 2

Lets not forget the model underneath

on ( ) off ( )

setBPM ( )

getBPM ( )

Beat Model

The BeatModel is the heart of the application. It implements the logic to start and stop the beat, set the beats per minute, and generate the sound.

The model also allows us to obtains its current state through the getBPM( ) method.

Page 313: Chapter 2

Building the pieces

public interface BeatModelInterface { void initialize ( );

void on ( );void off ( );void setBPM (int bpm);int getBPM ( );void registerObserver (BeatObserver o);void removeObserver (BeatObserver o);void registerObserver (BPMObserver o);void removeObserver (BPMObserver o);

}

This gets called after the BeatModel is instantiated.

These methods turn the beat generator on and off.

This method sets the beats per minute. After it is called, the beat frequency changes immediately.

The getBPM ( ) method returns the current BPMs, or 0 if the generator is off.

We’ve split this into two kinds of observers: observers that want to be notified on every beat, and observers that just want to be notified with the beats per minute changes.

This should look familiar, these methods allow objects to register as observers for state changes.

These are the methods that a controller will use to direct the model based on user interaction.

These methods allow the view and controller to get state and become observers.

Page 314: Chapter 2

Now lets take a look at the concrete BeatModel class…. public class BeatModel implements BeatModelInterface, MetaEventListener { Sequencer sequencer; ArrayList beatObservers = new ArrayList(); ArrayList bpmObservers = new ArrayList(); int bpm = 90;

// other instance variables public void initialize() {

setUpMidi(); buildTrackAndStart();

} public void on() { sequencer.start(); setBPM(90); } public void off() { setBPM(0); sequencer.stop(); } public void setBPM (int bpm) { this.bpm = bpm; sequencer.setTempoInBPM(getBPM()); notifyBPMObservers(); } public int getBPM() { return bpm; }

void beatEvent ( ) {notifyBeatObservers ( );

}// code to register and notify observers// Lots of MIDI code to handle the beat.

}

We implement the BeatModelInterface. This is needed for the

MIDI code.

The sequencer is the object that knows how to generate the real beats (that you can hear!)

The ArrayLists hold the two kinds of Observers

bpm holds the frequency of beats. Default = 90.

This method does setup for the sequencer and sets up the beat tracks for us. The on() and off ( ) starts

and shuts off the sequencer.

(1) Sets the bpm instance variable (2) Asks the sequencer to change its beats (3) Notifies all BPM observers that the BPM has changed.

The beatEvent ( ) method, which is not in the BeatModelInterface, is called by the MIDI code whenever a new beat starts. This notifies all BeatObservers that a new beat has just occurred.

Page 315: Chapter 2

Implementing the View (just an outline!) public class DJView implements ActionListener, BeatObserver, BPMObserver {

BeatModelInterface model;ControllerInterface controller;JFrame viewFrame;JPanel viewPanel;BeatBar beatBar;JLabel bpmOutputLabel;

public DJView ( ControllerInterface controller, BeatModelInterface model) {this.controller = controller;this.model = model;model.registerObserver ( (BeatObserver) this);model.registerObserver ((BPMObserver)this);

}

public void createView ( ){// create all Swing components here

}public void updateBPM ( ) {

int bpm = model.getBPM ( );if (bpm == 0) {

bpmOutputLabel.setText (“offline”);} else {

bpmOutputLabel.setText(“Current BPM: “ + model.getBPM ( ));}

}public void updateBeat ( ) {

beatBar.setValue (100);}

}

DJView is an observer for both the real-time beats and BPM changes.

The view holds a reference to both the model and the controller.

The updateBPM ( ) method is called when a state change occurs in the model. When that happens we update the display with the current BPM. We can get this value by requesting it directly from the model.

Likewise, the updateBeat ( ) method is called when the model starts a new beat. When that happens, we need to pulse our “beatbar”. We do this by setting it to its maximum value and letting it handle the animation of the pulse.

Page 316: Chapter 2

The DJView continued… (the user interface control) public class DJView implement ActionListener, BeatObserver, BPMObserver {

BeatModelInterface model;ControllerInterface controller;Jlabel bpmLabel;JTextField bpmTextField;Jbutton setBPMButton;Jbutton increaseBPMButton;Jbutton decreaseBPMButton;JMenuBar menuBar;Jmenu menu;JMenuItem startMenuItem;JMenuItem stopMenuItem;

public void createControls ( ) {// create all Swing components

}public void enableStopMenuItem ( ){

stopMenuItem.setEnabled(true);}public void disableStopMenuItem ( ){

stopMenuItem.setDisabled (true);}// same for startMenuItem

public void actionPerformed (ActionEvent event) {if (event.getSource ( ) == setBPMButton) {

int bpm = Integer.parseInt (bpmTextField.getText ( ) );controller.setBPM (bpm);

} else if (event.getSource( ) == increaseBPMButton) {controller.increaseBPM () ;

} else if (event.getSource( ) == decreaseBPMButton) {controller.decreaseBPM () ;

}}

}

If the Set button is clicked then it is passed on to the controller along with the new bpm.

Likewise if increase or decrease buttons are clicked, this information is passed on to the controller.

This method is called when a button is clicked.

Page 317: Chapter 2

Now for the Controller….

Remember - the controller is the strategy that we plug into the view.

What does a Strategy pattern look like? What do we need?

public interface ControllerInterface {void start ( );void stop ( );void increaseBPM ( );void decreaseBPM ( );void setBPM (int bpm);

}

Here are all the methods that a view can call on the controller

These should all look familiar after seeing the model’s interface. You can start and stop the beat generation, and change the BPM. This interface is “richer” than the BeatModel interface because you can adjust the BPMs with increase and decrease.

Page 318: Chapter 2

The Controller public class BeatController implements ControllerInterface { BeatModelInterface model; DJView view; public BeatController(BeatModelInterface model) { this.model = model; view = new DJView(this, model); view.createView(); view.createControls(); view.disableStopMenuItem(); view.enableStartMenuItem(); model.initialize(); } public void start() { model.on(); view.disableStartMenuItem(); view.enableStopMenuItem(); } public void stop() { model.off(); view.disableStopMenuItem(); view.enableStartMenuItem(); } public void increaseBPM() { int bpm = model.getBPM(); model.setBPM(bpm + 1); } public void decreaseBPM() { int bpm = model.getBPM(); model.setBPM(bpm - 1); } public void setBPM (int bpm) {

model.setBPM (bpm); }}

Controller implements the ControllerInterface!

The controller is the creamy stuff in the middle of the MVC oreo cookie, so it is the object that gets to hold on to the view and the model and glues it all together.

The controller is passed the model in the constructor and then creates the view.

When you choose Start from the user interface menu, the controller turns the model on and then alters the user interface to that the start menu item is disabled and the stop menu item is enabled.

Note: the controller is making the intelligent decision for the view. The view just knows how to turn menu items on and off; it doesn’t know the situations in which it should disable or enable them.

Page 319: Chapter 2

Putting it all together… public class DJTestDrive {

public static void main (String[] args) {BeatModelInterface model = new BeatModel ( );ControllerInterface controller = new BeatController (model);

} }

First create the model…

…..then create a controller and pass it the model. Remember, the controller creates the view, so we don’t have to do that.

Page 320: Chapter 2

Question

You have a beat rate and a pulse? What does that sound like? -- A heartbeat

What would you need to do to modify your MVC beat model to work with a heartbeat?

Page 321: Chapter 2

MVC and the Web With the coming of the Web, the MVC model was adapted to fit

the browser/server model. – The prevailing adaptation is called Model 2.

Here’s how Model 2 works:

(1) HTTP Request

(2) Instantiates

(3)

(4)(5) HTTP Response

JSP/view

Servlet/controller

Client

Model/DB/buisness logicbean

The servlet acts as a controller and processes the request - most likely making requests on the model (db). The result of processing the request is usually bundled up in the form of a Javabean

The controller forwards control to the view. The view is represented by a JSP. The JSP’s only job is to generate the page representing the view of the model.

Page 322: Chapter 2

Summary The MVC Pattern is a compound pattern consisting of the Observer, Strategy and Composite

patterns.

The model makes use of the Observer pattern so that it can keep observers updated, yet stay decoupled from them.

The controller is the strategy for the view. The view can use different implementations of the controller to get different behavior.

The view uses Composite Pattern to implement the user interface, which usually consists of nested components like panels, frames, and buttons.

These patterns work together to decouple the three players in the MVC model, which keeps designs clear and flexible.

The Adapter pattern can be used to adapt a new model to an existing view and controller.

Model 2 is an adaptation of the MVC for web applications.

In Model 2, the controller is implemented as a servlet and JSP and HTML implement the view.


Recommended