0% found this document useful (0 votes)
6 views188 pages

OOP2026_L8_JavaSlides_JavaDesignPatterns

The document provides an overview of design patterns in software development, particularly focusing on their importance in object-oriented programming using Java. It discusses various design patterns such as Strategy, Singleton, and Observer, and emphasizes the benefits of using these patterns for creating flexible, maintainable, and reusable code. Additionally, it outlines the SOLID principles and the criteria for designing object-oriented systems, highlighting the significance of understanding and applying design patterns effectively.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views188 pages

OOP2026_L8_JavaSlides_JavaDesignPatterns

The document provides an overview of design patterns in software development, particularly focusing on their importance in object-oriented programming using Java. It discusses various design patterns such as Strategy, Singleton, and Observer, and emphasizes the benefits of using these patterns for creating flexible, maintainable, and reusable code. Additionally, it outlines the SOLID principles and the criteria for designing object-oriented systems, highlighting the significance of understanding and applying design patterns effectively.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Object-Oriented Programming

Using Java
Design Patterns

Quan Thai Ha

HUS
2024
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

1 186
Design Patterns

2 186
Design Patterns

3 186
Design Patterns are Everywhere

In 1995, a book was published by the “Gang of Four” called Design Patterns.
▶ It applied the concept of patterns (discussed next) to software design and described 23 of them.

- The authors did not invent these patterns. Instead, they included patterns they found in at least 3
“real” software systems.

Since that time lots of Design Patterns books have been published.
▶ And more patterns have been cataloged.

Unfortunately, many people feel like they should become experts in object-oriented
analysis and design before they learn about patterns.
▶ The book takes a different stance: learning about design patterns will help you become an
expert in object-oriented analysis and design.

4 186
Christopher Alexander (I)

Design patterns in software design traces its intellectual roots to work performed in the
1970s by an architect named Christopher Alexander.
▶ His 1979 book called "The Timeless Way of Building" that asks the question "Is quality
objective?".
- In particular, "What makes us know when an architectural design is good? Is there an objective
basis for such a judgement?".
▶ His answer was "yes" that it was possible to objectively define "high quality" or "beautiful"
buildings.
He studied the problem of identifying what makes a good architectural design by
observing all sorts of built structures.
▶ Buildings, towns, streets, homes, community centers, etc.

When he found an example of a high quality design, he would compare that object to other
objects of high quality and look for commonalties.
▶ Especially if both objects were used to solve the same type of problem.

5 186
Christopher Alexander (II)

By studying high quality structures that solve similar problems, he could discover
similarities between the designs and these similarities where what he called patterns.
▶ "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".
▶ The pattern provides an approach that can be used to achieve a high quality solution to its
problem.
Alexander identified four elements to describe a pattern.
▶ The name of the pattern.
▶ The purpose of the pattern: what problem it solves.
▶ How to solve the problem.
▶ The constraints we have to consider in our solution.

He also felt that multiple patterns applied together can help to solve complex architectural
problems.

6 186
Design Patterns and Software

Work on design patterns got started when people asked:


▶ Are there problems in software that occur all the time that can be solved in somewhat the
same manner?
▶ Was it possible to design software in terms of patterns?

Many people felt the answer to these questions was “yes” and this initial work influenced
the creation of the Design Patterns book by the Gang of Four.
▶ It catalogued 23 patterns: successful solutions to common problems that occur in software
design.
Design patterns, then, assert that the quality of software systems can be measured
objectively.
▶ What is present in a good quality design (X’s) that is not present in a poor quality design?
▶ What is present in a poor quality design (Y’s) that is not present in a good quality design?

We would then want to maximize the X’s while minimizing the Y’s in our own designs.

7 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

8 186
What are Design Patterns
As a developer, it is our responsibility to design the code in such a way which allow our
code to be flexible, maintainable, and re-usable.
▶ The code we have written is flexible enough that we can make any changes to it with less or
any pain. Our code is re-usable so that we can re-use it anywhere without any trouble. We can
maintain our code easily and any changes to a part of the code will not affect any other part
of the code.
Designing is an art and it comes with the experience. But there are some set of solutions
already written by some of the advanced and experienced developers while facing and
solving similar designing problems. These solutions are known as Design Patterns.
The Design Patterns is the experience in designing the object oriented code.
Design Patterns are general reusable solution to commonly occurring problems. These are
the best practices, used by the experienced developers. Patterns are not complete code, but
it can use as a template which can be applied to a problem. Patterns are re-usable; they can
be applied to similar kind of design problem regardless to any domain. In other words, we
can think of patterns as a formal document which contains recurring design problems and
its solutions.

9 186
Key Features of a Pattern

"Descriptions of communicating objects and classes that are customized to solve a general
design problem in a particular context."
[Gamma, Helm, Johnson, Vlissides 1995]

▶ Name.
▶ Intent: The purpose of the pattern.
▶ Problem: What problem does it solve?
▶ Solution: The approach to take to solve the problem.
▶ Participants: The entities involved in the pattern.
▶ Consequences: The effect the pattern has on your system.
▶ Structure: Class Diagram.
▶ Implementation: Example ways to implement the pattern.
▶ Sample code.
▶ Related patterns.

10 186
Why Study Design Patterns?

Flexibility
▶ Using design patterns your code becomes flexible. It helps to provide the correct level of
abstraction due to which objects become loosely coupled to each other which makes your
code easy to change.
Reusability
▶ Loosely coupled and cohesive objects and classes can make your code more reusable. This
kind of code becomes easy to be tested as compared to the highly coupled code.
Shared Vocabulary
▶ Shared vocabulary makes it easy to share your code and thought with other team members. It
creates more understanding between the team members related to the code.
Capture best practices
▶ Design patterns capture solutions which have been successfully applied to problems. By
learning these patterns and the related problem, an inexperienced developer learns a lot about
software design.

11 186
A Sense of Perspective

Design patterns provide you not with code reuse but with experience reuse.
▶ Knowing concepts such as abstraction, inheritance and polymorphism will NOT make you a
good designer, unless you use those concepts to create flexible designs that are maintainable
and that can cope with change.

Design patterns can show you how to apply those concepts to achieve those goals.

Design Patterns give you a higher-level perspective on:


▶ The problems that come up in object-oriented analysis and design work.
▶ The process of design itself.
▶ The use of object orientation to solve problems.

You’ll be able to think more abstractly and not get bogged down in implementation details
too early in the process.

12 186
Other Advantages

Improved Motivation of Individual Learning in Team Environments.


▶ Junior developers see that the design patterns discussed by more senior developers are
valuable and are motivated to learn them.

Improved maintainability.
▶ Many design patterns make systems easy to extend, leading to increased maintainability.

Design patterns lead to a deeper understanding of core OO principles.

They reinforce useful design heuristics such as:


▶ Code to an interface.
▶ Favor delegation over inheritance.
▶ Find what varies and encapsulate it.

Since they favor delegation, they help you avoid the creation of large inheritance
hierarchies, reducing complexity.

13 186
Criteria to design Object-Oriented

Modularity
▶ Ease the management (object technology).

Cohesion
▶ Measure of relatedness or consistency in the functionality of a software unit.
▶ Cohesion is the degree to which the elements inside a module belong together.
▶ Strong cohesion is good quality.

Coupling
▶ Degree with which methods of different modules are dependent on each other.
▶ A loose coupling is good quality.

Reusability
▶ Libraries, frameworks.

14 186
The SOLID Principles

Guidelines that, when followed, can dramatically enhance the maintainability of software.
▶ Single Responsibility Principle (SRP). The SRP states that each class or similar unit of code
should have one responsibility only and, therefore, only one reason to change.
▶ Open / Closed Principle (OCP). The OCP states that all classes and similar units of source
code should be open for extension but closed for modification.
▶ Liskov Substitution Principle (LSP). The LSP specifies that functions that use references to
base classes must be able to use objects of derived classes without knowing it.
▶ Interface Segregation Principle (ISP). The ISP specifies that clients should not be forced to
depend upon interfaces that they do not use. Instead, those interfaces should be minimised.
▶ Dependency Inversion Principle (DIP). The DIP states that high level modules should not
depend upon low level modules and that abstractions should not depend upon details.

15 186
Original Catalogue of Patterns

16 186
Creational patterns

Creational design patterns are used to design the instantiation process of objects. The
creational pattern uses the inheritance to vary the object creation.

There are two recurring themes in these patterns. First, they all encapsulate knowledge
about which concrete classes the system uses. Second, they hide how instances of these
classes are created and put together.
▶ Consequently, the creational patterns give you a lot of flexibility in what gets created, who
creates it, how it gets created, and when.

There can be some cases when two or more patterns looks fit as a solution to a problem. At
other times, the two patterns complement each other, for example, Builder can be used
with other pattern to implements which components to get built.

17 186
Creational patterns

Factory Method define an interface for creating an object, but let subclasses decide which
class to instantiate. Factory Method lets a class defer instantiation to subclasses.
Abstract Factory provide an interface for creating families of related or dependent objects
without specifying their concrete classes.
Builder separate the construction of a complex object from its representation so that the
same construction process can create different representations.
Prototype specify the kinds of objects to create using a prototypical instance, and create
new objects by copying this prototype.
Singleton ensure a class only has one instance, and provide a global point of access to it.

18 186
Structural patterns

Structural patterns are concerned with how classes and objects are composed to form
larger structures. Structural class patterns use inheritance to compose interfaces or
implementations.
▶ As a simple example, consider how multiple inheritance mixes two or more classes into one.
The result is a class that combines the properties of its parent classes. This pattern is
particularly useful for making independently developed class libraries work together.

Rather than composing interfaces or implementations, structural object patterns describe


ways to compose objects to realize new functionality.
▶ The added flexibility of object composition comes from the ability to change the composition
at run-time, which is impossible with static class composition.

19 186
Structural patterns

Adapter convert the interface of a class into another interface clients expect. Adapter lets
classes work together that couldn’t otherwise because of incompatible interfaces.
Bridge decouple an abstraction from its implementation so that the two can vary
independently.
Composite compose objects into tree structures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects uniformly.
Decorator attach additional responsibilities to an object dynamically. Decorators provide
a flexible alternative to subclassing for extending functionality.
Facade provide a unified interface to a set of interfaces in a subsystem. Facade defines a
higher-level interface that makes the subsystem easier to use.
Flyweight use sharing to support large numbers of fine-grained objects efficiently.
Proxy provide a surrogate or placeholder for another object to control access to it.

20 186
Behavior patterns

Behavioral patterns are concerned with algorithms and the assignment of responsibilities
between objects. Behavioral patterns describe not just patterns of objects or classes but
also the patterns of communication between them.
▶ These patterns characterize complex control flow that’s difficult to follow at run-time. They
shift your focus away from flow of control to let you concentrate just on the way objects are
interconnected.

Behavioral object patterns use object composition rather than inheritance. Some describe
how a group of peer objects cooperate to perform a task that no single object can carry out
by itself.
▶ An important issue here is how peer objects know about each other. Peers could maintain
explicit references to each other, but that would increase their coupling. In the extreme, every
object would know about every other. The Mediator pattern avoids this by introducing a
mediator object between peers. The mediator provides the indirection needed for loose
coupling.

21 186
Behavior patterns

Chain of Responsibility avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving objects and pass
the request along the chain until an object handles it.
Command encapsulate a request as an object, thereby letting you parameterize clients
with different requests, queue or log requests, and support undoable operations.
Interpreter given a language, define a represention for its grammar along with an
interpreter that uses the representation to interpret sentences in the language.
Iterator provide a way to access the elements of an aggregate object sequentially without
exposing its underlying representation.
Mediator define an object that encapsulates how a set of objects interact. Mediator
promotes loose coupling by keeping objects from referring to each other explicitly, and it
lets you vary their interaction independently.
Memento without violating encapsulation, capture and externalize an object’s internal
state so that the object can be restored to this state later.

22 186
Behavior patterns

Observer define a one-to-many dependency between objects so that when one object
changes state, all its dependents are notified and updated automatically.
State allow an object to alter its behavior when its internal state changes. The object will
appear to change its class.
Strategy define a family of algorithms, encapsulate each one, and make them
interchangeable. Strategy lets the algorithm vary independently from clients that use it.
Template Method define the skeleton of an algorithm in an operation, deferring some
steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm
without changing the algorithm’s structure.
Visitor represent an operation to be performed on the elements of an object structure.
Visitor lets you define a new operation without changing the classes of the elements on
which it operates.

23 186
How to select and use one?

There are a number of design patterns to choose from, to choose one, you must have good
knowledge of each one of them.
▶ There are many design patterns which look very similar to one another. They solve almost a
similar type of design problem and also have similar implementation.
▶ One must have a very deep understanding of them in order to implement the correct design
pattern for the specific design problem.

A design pattern can be used to solve more than one design problem, and one design
problem can be solved by more than one design patterns.
▶ There could be plenty of design problems and solutions for them, but, to choose the pattern
which fits exactly is depends on your knowledge and understanding about the design patterns.
▶ It also depends on the code you already have in place.

24 186
How to select and use one?

You need to identify the kind of design problem you are facing.
▶ A design problem can be categorized into creational, structural, or behavioral. Based to this
category you can filter the patterns and selects the appropriate one.

For example:
▶ There are too many instances of a class which represent only a single thing, the value
in the properties of the objects are same, and they are only used as read-only: you can
select the Singleton pattern for this design problem which ensures only a single instance for
the entire application. It also helps to decrease the memory size.
▶ Classes are too much dependent on each other. A Change in one class affects all other
dependent classes: you can use Bridge, Mediator, or Command to solve this design
problem.
▶ There are two different incompatible interfaces in two different parts of the code, and
your need is to convert one interface into another which is used by the client code to
make the entire code work: the Adapter pattern fits into this problem.

25 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

26 186
Design Patterns by Example
DuckSimulator: a "Duck Pond Simulator" that can show a wide variety of duck species
swimming and quacking in a pond.
The initial designers of the system used standard OO techniques and created one Duck
superclass from which all other duck types inherit.

27 186
Easy

But a request has arrived to allow ducks to also fly.

28 186
Whoops!

29 186
Double Whoops!

30 186
What about an Interface?

Hear we define two interfaces and allow subclasses to implement the interfaces thay need.
What are the trade-offs?

31 186
Design Trade-offs

With inheritance, we get:


▶ Code reuse, only one fly() and quack() method vs. multiple (pro).
▶ Common behavior in root class, not so common after all (con).

With interfaces, we get:


▶ Specificity: only those subclasses that need a fly() method get it (pro).
▶ No code re-use: since interfaces only define signatures (con)

Use of abstract base class over an interface? Could do it, but only in languages that
support multiple inheritance.
▶ In this approach, you implement Flyable and Quackable as abstract base classes and then
have Duck subclasses use multiple inheritance.

32 186
Design Principles to the Rescue!
Encapsulate what varies
▶ For this particular problem, the "what varies" is the behaviors between Duck subclasses. We
need to pull out behaviors that vary across the subclasses and put them in their own classes
(i.e., encapsulate them.)
- Duck will no longer have fly() and quack() methods directly.
- Create two sets of classes, one that implements fly behaviors and one that implements quack
behaviors.
▶ Benefits: fewer unintended consequences from code changes (such as when we added fly() to
Duck) and more flexible code.
Code to an interface
▶ We’ll make use of the "code to an interface" principle and make sure that each member of the
two sets implements a particular interface.
- For QuackBehavior, we’ll have Quack, Squeak, MuteQuack...
- For FlyBehavior, we’ll have FlyWithWings, FlyNoWay, FlyWhenThrown, ...
▶ Additional Benefits: Other classes can gain access to these behaviors and we can add
additional behaviors without impacting other classes.
33 186
"Code to an interface" does NOT imply Java Interface

We are overloading the word "interface" when we say "code to an interface":


▶ We can implement "code to an interface" by defining a Java interface and then have various
classes implement that interface.
▶ Or, we can "code to a supertype" and instead define an abstract base class which classes can
access via inheritance.

When we say "code to an interface" it implies that the object that is using the interface will
have a variable whose type is the supertype (whether it is an interface or an abstract
base class) and thus
▶ can point at any implementation of that supertype,
▶ and is shielded from their specific class names.
- A Duck will point to a fly behavior with a variable of type FlyBehavior NOT FlyWithWings; the
code will be more loosely coupled as a result.

34 186
Bringing it all Together: Delegation

To take advantage of these new behaviors, we must modify Duck to delegate its flying and
quacking behaviors to these other classes
▶ rather than implementing this behavior internally.

We’ll add two attributes that store the desired behavior and we’ll rename fly() and quack()
to performFly() and performQuack().
▶ This last step is meant to address the issue of it not making sense for a DecoyDuck to have
methods like fly() and quack() directly as part of its interface.
- Instead, it inherits these methods and plugs-in CantFly and Silence behaviors to make sure that it
does the right things if those methods are invoked.

This is an instance of the principle "Favor delegation over inheritance".

35 186
The Big Picture on encapsulated behaviors

36 186
New Class Diagram

FlyBehavior and QuackBehavior define a set of behaviors that provide behavior to Duck.
Duck delegates to each set of behaviors and can switch among them dynamically, if
needed.
While each subclass now has a performFly() and performQuack() method, at least the user
interface is uniform and those methods can point to null behaviors when required.

37 186
DuckSimulator Code

1 public interface FlyBehavior {


void f l y ( ) ;
3 }

5 p u b l i c c l a s s FlyWithWings i m p l e m e n t s F l y B e h a v i o r {
public void f l y ( ) {
7 System . o u t . p r i n t l n ( " I ’m f l y i n g ! ! " ) ;
}
9 }

11 p u b l i c c l a s s FlyRocketPowered implements F l y B e h a v i o r {
public void f l y ( ) {
13 System . o u t . p r i n t l n ( " I ’m f l y i n g w i t h a r o c k e t " ) ;
}
15 }

17 p u b l i c c l a s s FlyNoWay i m p l e m e n t s F l y B e h a v i o r {
public void f l y ( ) {
19 System . o u t . p r i n t l n ( " I can ’ t f l y " ) ;
}
21 }

38 186
DuckSimulator Code

1 p u b l i c i n t e r f a c e QuackBehavior {
v o i d quack ( ) ;
3 }

5 p u b l i c c l a s s Squeak i m p l e m e n t s Q u a c k B e h a v i o r {
p u b l i c v o i d quack ( ) {
7 System . o u t . p r i n t l n ( " Squeak " ) ;
}
9 }

11 p u b l i c c l a s s Quack i m p l e m e n t s Q u a c k B e h a v i o r {
p u b l i c v o i d quack ( ) {
13 System . o u t . p r i n t l n ( " Quack " ) ;
}
15 }

17 p u b l i c c l a s s MuteQuack i m p l e m e n t s Q u a c k B e h a v i o r {
p u b l i c v o i d quack ( ) {
19 System . o u t . p r i n t l n ( " << S i l e n c e >> " ) ;
}
21 }

39 186
DuckSimulator Code

1 p u b l i c a b s t r a c t c l a s s Duck {
protected FlyBehavior flyBehavior ;
3 p r o t e c t e d QuackBehavior quackBehavior ;

5 p u b l i c Duck ( ) { ... }

7 public void setFlyBehavior ( FlyBehavior flyBehavior ) { ... }

9 p u b l i c v o i d s e t Q u a c k B e h a v i o r ( Q u a c k B e h a v i o r quackBehaviow ) { ... }

11 abstract void display ( ) ;

13 public void performFly ( ) {


flyBehavior . fly () ;
15 }

17 p u b l i c v o i d performQuack ( ) {
q u a c k B e h a v i o r . quack ( ) ;
19 }

21 p u b l i c v o i d swim ( ) {
System . o u t . p r i n t l n ( " A l l d u c k s f l o a t , even d e c o y s ! " ) ;
23 }
}

40 186
DuckSimulator Code

p u b l i c c l a s s MallardDuck e x t e n d s Duck {
2 p u b l i c MallardDuck ( ) {
q u a c k B e h a v i o r = new Quack ( ) ;
4 f l y B e h a v i o r = new FlyWithWings ( ) ;
}
6
public void display ( ) {
8 System . o u t . p r i n t l n ( " I ’m a r e a l M a l l a r d duck " ) ;
}
10 }

12
p u b l i c c l a s s RedHeadDuck e x t e n d s Duck {
14 p u b l i c RedHeadDuck ( ) {
f l y B e h a v i o r = new FlyWithWings ( ) ;
16 q u a c k B e h a v i o r = new Quack ( ) ;
}
18
public void display ( ) {
20 System . o u t . p r i n t l n ( " I ’m a r e a l Red Headed duck " ) ;
}
22 }

41 186
DuckSimulator Code

p u b l i c c l a s s RubberDuck e x t e n d s Duck {
2 p u b l i c RubberDuck ( ) {
f l y B e h a v i o r = new FlyNoWay ( ) ;
4 q u a c k B e h a v i o r = new Squeak ( ) ;
}
6
p u b l i c RubberDuck ( F l y B e h a v i o r f l y B e h a v i o r , Q u a c k B e h a v i o r q u a c k B e h a v i o r ) { ... }
8
public void display ( ) {
10 System . o u t . p r i n t l n ( " I ’m a r u b b e r d u c k i e " ) ;
}
12 }

14 p u b l i c c l a s s DecoyDuck e x t e n d s Duck {
p u b l i c DecoyDuck ( ) {
16 s e t F l y B e h a v i o r ( new FlyNoWay ( ) ) ;
s e t Q u a c k B e h a v i o r ( new MuteQuack ( ) ) ;
18 }

20 public void display ( ) {


System . o u t . p r i n t l n ( " I ’m a duck Decoy " ) ;
22 }
}

42 186
DuckSimulator Code

1 p u b l i c c l a s s DuckSimulator {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 L i s t <Duck > d u c k s = new L i n k e d L i s t < > ( ) ;
d u c k s . add ( new MallardDuck ( ) ) ;
5 d u c k s . add ( new DecoyDuck ( ) ) ;
d u c k s . add ( new RedheadDuck ( ) ) ;
7 Duck myDuck = new RubberDuck ( ) ; / / Note : v a r i a b l e i s t y p e Duck , n o t t h e
/ / s p e c i f i c s u b t y p e s ( Code t o i n t e r f a c e ) .
9 d u c k s . add ( myDuck ) ;

11 p r o c e s s D u c k s ( d u ck s ) ;

13 / / Change b e h a v i o r s o f d u c k s d y n a m i c a l l y .
/ / Here we s e e t h e power o f d e l e g a t i o n , we can change b e h a v i o r s a t run − t i m e
15 myDuck . s e t F l y B e h a v i o r ( new F l y R o c k e t P o w e r e d ( ) ) ;
myDuck . s e t Q u a c k B e h a v i o r ( new Speak ( ) ) ;
17
p r o c e s s D u c k s ( d u ck s ) ;
19 }

43 186
DuckSimulator Code

1 /∗
∗ B e c a u s e o f a b s t r a c t i o n and polymorphism , p r o c e s s D u c k s ( )
3 ∗ c o n s i s t s o f n i c e , c l e a n , r o b u s t , and e x t e n s i b l e code !
∗/
5 p u b l i c s t a t i c v o i d p r o c e s s D u c k s ( L i s t <Duck > d u c k s ) {
f o r ( Duck duck : d u c k s ) {
7 System . o u t . p r i n t l n ( " −−−−−−−−−−−−−−−−−−−− " ) ;
System . o u t . p r i n t l n ( " Name : " + duck . g e t C l a s s ( ) . getName ( ) ) ;
9 duck . d i s p l a y ( ) ;
duck . performQuack ( ) ;
11 duck . p e r f o r m F l y ( ) ;
duck . swim ( ) ;
13 }

15 System . o u t . p r i n t l n ( " Done p r o c e s s i n g d u c k s ! " ) ;


}
17 }

44 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

45 186
Definition of Strategy Pattern

The solution that we applied to this design problem is known as the Strategy Design
Pattern. It features the following design concepts/principles:
▶ Encapsulate what varies
▶ Code to an Interface, not implementations
▶ Favor delegation over inheritance

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

Creating systems using delegation gives you a lot more flexibility. Not only does it let you
encapsulate a family of algorithms into their own set of classes, but it also lets you change
behavior at runtime as long as the object you’re composing with implements the correct
behavior interface.

46 186
Structure of Strategy Pattern

Algorithm is pulled out of Host. Client only makes use of the public interface of Algorithm
and is not tied to concrete subclasses.
Client can change its behavior by switching among the various concrete algorithms.

47 186
Structure of Delegate

Purpose of Delegate:
▶ Allow an object’s behavior to be customized without forcing a developer to create a subclass
that overrides default behavior.
Client invokes method on Host; Host checks to see if Delegate handles this method; if so, it
routes the call to the Delegate; if not, it provides default behavior for the method.
▶ Here, if Client invokes methodA() on Host, the Delegate’s customizeMethodA() will be
invoked at some point to help customize Host’s behavior for methodA().
48 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

49 186
Singleton Pattern

Let’s derive this pattern by starting with a class that has no restrictions on who can create
it.

1 public class Ball {


private String color ;
3
public B a l l ( S t r i n g c o l o r ) {
5 this . color = color ;
}
7
p u b l i c v o i d bounce ( ) {
9 System . o u t . p r i n t l n ( " Boing ! " ) ;
}
11 }

13 B a l l b a l l 1 = new B a l l ( " Red " ) ;


B a l l b a l l 2 = new B a l l ( " B l u e " ) ;
15
/ / As l o n g a s a c l i e n t o b j e c t knows a b o u t t h e name o f c l a s s B a l l , i t can c r e a t e
17 // i n s t a n c e s o f B a l l . T h i s i s b e c a u s e t h e constructor is public .
/ / We can s t o p u n a u t h o r i z e d c r e a t i o n o f B a l l i n s t a n c e s by making the constructor private .

50 186
Singleton Pattern

public class Ball {


2 private String color ;

4 private B a l l ( S t r i n g c o l o r ) {
this . color = color ;
6 }

8 p u b l i c v o i d bounce ( ) {
System . o u t . p r i n t l n ( " Boing ! " ) ;
10 }
}
12

14 public class TestBall {


p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
16 B a l l b a l l = new B a l l ( " Red " ) ; / / ERROR
/ / Now I n s t a n t i a t i o n o f B a l l i s i m p o s s i b l e by any method o u t s i d e o f B a l l .
18 }
}

51 186
Singleton Pattern

Now that the constructor is private, no class can gain access to instances of Ball.
▶ But our requirements were that there would be at least one way to get access to an instance of
Ball.

We need a method to return an instance of Ball.


▶ But since there is no way to get access to an instance of Ball, the method CANNOT be an
instance method.
- This means it needs to be a class method, aka a static method.

52 186
Singleton Pattern

1 public class Ball {


private String color ;
3
private B a l l ( S t r i n g c o l o r ) {
5 this . color = color ;
}
7
p u b l i c v o i d bounce ( ) {
9 System . o u t . p r i n t l n ( " Boing ! " ) ;
}
11
p u b l i c static B a l l getInstance ( S t r i n g c o l o r ) {
13 r e t u r n new B a l l ( c o l o r ) ;
}
15 }

17
public class TestBall {
19 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
B a l l b a l l = new B a l l ( " Red " ) ; / / ERROR
21 / / Now I n s t a n t i a t i o n o f B a l l i s i m p o s s i b l e by any method o u t s i d e o f B a l l .
B a l l b a l l = B a l l . g e t I n s t a n c e ( " Blue " ) ; / / OK
23 }
}

53 186
Singleton Pattern

To ensure only one instance is ever


created,
public class Ball {
2 p r i v a t e static Ball ball ; ▶ need a static variable to store that
private String color ;
4
instance.
private Ball ( String color ) {
6 this . color = color ; - No instance variables are
} available in static methods.
8
p u b l i c v o i d bounce ( ) {
10 System . o u t . p r i n t l n ( " Boing ! " ) ; Now the getInstance() method
}
12 returns null each time it is called.
public static Ball getInstance ( String color ) {
14 return ball ; ▶ Need to check the static variable
16 }
} to see if it is null.
- If so, create an instance.
▶ Otherwise return the single
instance.

54 186
Singleton Pattern

The code shows the Singleton


pattern:
public class Ball {
2 private static Ball ball ; ▶ private constructor.
private String color ;
4 ▶ private static variable to store the
private Ball ( String color ) {
6 this . color = color ;
single instance.
} ▶ public static method to gain access
8
p u b l i c v o i d bounce ( ) { to that instance.
10 System . o u t . p r i n t l n ( " Boing ! " ) ;
} - This method creates object if
12
public static Ball getInstance ( String color ) {
needed; returns it.
14 / / Lazy i n s t a n t i a t i o n
i f ( b a l l == n u l l ) {
16 b a l l = new B a l l ( c o l o r ) ; But this code ignores the fact that a
18
}
return ball ;
parameter is being passed in.
} ▶ so if a “Red” ball is created all
20 }
subsequent requests for a "Green"
ball are ignored.

55 186
Singleton Pattern

The solution to the final problem is to change the private static instance variable to a Map.
Then check if the map contains an instance for a given value of the parameter.
▶ This ensures that only one ball of a given color is ever created.
▶ This is a very acceptable variation of the Singleton pattern.

...
2 p r i v a t e s t a t i c Map< S t r i n g , B a l l > b a l l R e c o r d = new HashMap . . .
...
4
public static Ball getInstance ( String color ) {
6 i f ( ! ballRecord . containsKey ( color ) ) {
b a l l R e c o r d . p u t ( c o l o r , new Ball ( color ) ) ;
8 }
return ballRecord . get ( color ) ;
10 }

56 186
Definition of Singleton Pattern

Singleton Pattern
Singleton Pattern used to ensure that only one instance of a particular class ever gets created
and that there is just one (global) way to gain access to that instance.

What’s really going on here?


- We’re taking a class and letting it manage a single instance of itself.
- We’re also preventing any other class from creating a new instance on its own.
- To get an instance, you’ve got to go through the class itself.
We’re also providing a global access point to the instance:
- Whenever you need an instance, just query the class and it will hand you back the single
instance.
- We can implement this so that the Singleton is created in a lazy manner, which is especially
important for resource-intensive objects.

57 186
Structure of Singleton Pattern

Singleton involves only a single class (not typically called Singleton). That class is a
full-fledged class with other attributes and methods (not shown).
The class has a static variable that points at a single instance of the class.
The class has a private constructor (to prevent other code from instantiating the class) and
a static method that provides access to the single instance.

58 186
Real World Examples

Centralized manager of resources:


▶ Window manager
▶ File system manager
▶ ···

Logger classes
Factories
▶ Especially those that issue IDs.
▶ Singleton is often combined with Factory Method and Abstract Factory patterns.

59 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

60 186
Adapters in real world

Adapter pattern provides steps for converting


an incompatible interface with an existing
system into a different interface that is
compatible.

Real world example: AC power adapters.


▶ Electronic products made for the USA
cannot be used directly with outlets found
in most other parts of the world.
▶ To use these products outside the US, you
need an AC power adapter.

61 186
Software Adapters

Pre-condition: You are maintaining an


existing system that makes use of a third-party
library from vendor A.
Stimulus: Vendor A goes belly up and
corporate policy does not allow you to make
use of an unsupported class library.
Response: Vendor B provides a similar library
but its interface is completely different from . . . plug it in
the interface provided by vendor A.
Assumptions: You don’t want to change your
code, and you can’t change vendor B’s code.
Solution: Write new code that adapts vendor
B’s interface to the interface expected by your
original code.

62 186
Example: A Turkey Amongst Ducks!

A slightly different duck model.

p u b l i c i n t e r f a c e Duck {
2 v o i d quack ( ) ;
void f l y ( ) ;
4 }

p u b l i c c l a s s MallardDuck i m p l e m e n t s Duck {
2 p u b l i c v o i d quack ( ) {
System . o u t . p r i n t l n ( " Quack " ) ;
4 }

6 public void f l y ( ) {
System . o u t . p r i n t l n ( " I ’m f l y i n g " ) ;
8 }
}

63 186
Example: A Turkey Amongst Ducks!

An interloper wants to invade the simulator.

1 p u b l i c i n t e r f a c e Tu r k e y {
public void gobble ( ) ;
3 public void f l y ( ) ;
}

p u b l i c c l a s s W i l d T u r k e y i m p l e m e n t s Tu r k e y {
2 public void gobble ( ) {
System . o u t . p r i n t l n ( " Gobble Gobble " ) ;
4 }

6 public void f l y ( ) {
System . o u t . p r i n t l n ( " I ’m f l y i n g a s h o r t d i s t a n c e " ) ;
8 }
}

64 186
Example: A Turkey Amongst Ducks!

But the duck simulator doesn’t know how to handle turkeys, only ducks!

Solution
If it walks like a duck and quacks like a duck, then it must be a duck!

Or. . .

It might be a turkey wrapped with a duck adapter!

65 186
Example: A Turkey Amongst Ducks!

1. Adapter implements target


interface (Duck).
1 p u b l i c c l a s s T u r k e y A d a p t e r i m p l e m e n t s Duck {
p r i v a t e Turkey tu rke y ; 2. Adaptee (turkey) is passed via
3
constructor and stored internally.
p u b l i c TurkeyAdapter ( Turkey t ur key ) {
t h i s . turkey = turkey ;
5
}
3. Calls by client code are
7 delegated to the appropriate
p u b l i c v o i d quack ( ) { methods in the adaptee.
9 turkey . gobble ( ) ;
} 4. Adapter is full-fledged class,
11
public void f l y ( ) { could contains additional
13 f o r ( i n t i = 0 ; i < 5 ; i ++) { variables and methods to get its
turkey . f l y ( ) ;
15 } job done; can be used
} polymorphically as a Duck.
17 }

66 186
Example: A Turkey Amongst Ducks!

1 p u b l i c c l a s s DuckSimulator {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 MallardDuck m a l l a r d D u c k = new MallardDuck ( ) ;

5 W i l d T u r k e y w i l d T u r k e y = new W i l d T u r k e y ( ) ;
/ / Swap t h e t u r k e y i n a T u r k e y A d a p t e r , which makes i t l o o k l i k e a Duck
7 Duck t u r k e y A d a p t e r = new T u r k e y A d a p t e r ( w i l d T u r k e y ) ;

9 L i s t <Duck > d u c k s = new L i n k e d L i s t < > ( ) ;


d u c k s . add ( m a l l a r d D u c k ) ;
11 d u c k s . add ( t u r k e y A d a p t e r ) ;

13 f o r ( Duck duck : d u c k s ) {
duck . quack ( ) ;
15 duck . f l y ( ) ;
}
17 }
}

67 186
The Adapter Pattern explained

Here’s how the Client uses the Adapter

1. The client makes a request to the


adapter by calling a method on it
using the target interface.
2. The adapter translates the request
into one or more calls on the
adaptee using the adaptee
interface.
3. The client receives the results of the
call and never knows there is an
adapter doing the translation.

Note that the Client and Adaptee


are decoupled – neither knows
about the other.
68 186
Definition of Adapter Pattern

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

Adapter Pattern allows us to


use a client with an incompatible
interface by creating an Adapter
that does the conversion.
This acts to decouple the client
from the implemented interface.
If we expect the interface to
change over time, the adapter
encapsulates that change so that
the client doesn’t have to be
modifi ed each time it needs to
operate against a different
interface.
69 186
Structure (I)

70 186
Structure (II)

71 186
Real World Adapters

Before Java’s new collection classes, iteration over a collection occurred via
[Link]
▶ hasMoreElements() : boolean
▶ nextElement() : Object

With the collection classes, iteration was moved to a new interface: [Link]
▶ hasNext(): boolean
▶ next(): Object
▶ remove(): void

There’s a lot of code out there that makes use of the Enumeration interface
▶ New code can still make use of that code by creating an adapter that converts from the
Enumeration interface to the Iteration interface.

72 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

73 186
Facade Example

Imagine a library of classes with a


complex interface and/or complex
interrelationships.

Home Theater System


▶ Amplifier, DvdPlayer, Projector,
CdPlayer, Tuner, Screen,
PopcornPopper, and TheaterLights.
▶ Each with its own interface and
interclass dependencies.

That’s a lot of classes, a lot of


interactions, and a big set of
interfaces to learn and use

74 186
Facade Example

Watching a movie (the hard way)

There’s just one thing – to watch the movie, you need to perform a few tasks:

1. Turn on the popcorn popper 8. Turn the sound amplifier on


2. Start the popper popping 9. Set the amplifier to DVD input
3. Dim the lights 10. Set the amplifier to surround sound
4. Put the screen down 11. Set the amplifier volume to medium (5)
5. Turn the projector on 12. Turn the DVD Player on
6. Set the projector input to DVD 13. Start the DVD Player playing
7. Put the projector on wide-screen mode

75 186
Facade Example

Let’s check out those same tasks in terms of the classes and the method calls needed to
perform them:

76 186
Facade Example

77 186
Facade Example

78 186
Facade Pattern Code

p u b l i c c l a s s PopcornPopper {
2 private String description ;

4 p u b l i c PopcornPopper ( S t r i n g d e s c r i p t i o n ) {
this . description = description ;
6 }

8 p u b l i c v o i d on ( ) {
System . o u t . p r i n t l n ( d e s c r i p t i o n + " on " ) ;
10 }

12 public void o f f ( ) {
System . o u t . p r i n t l n ( d e s c r i p t i o n + " o f f " ) ;
14 }

16 p u b l i c v o i d pop ( ) {
System . o u t . p r i n t l n ( d e s c r i p t i o n + " p o p p i n g p o p c o r n ! " ) ;
18 }

20 public String toString () {


return description ;
22 }
}

79 186
Facade Code

1 public c l a s s Screen {
private String description ;
3
public Screen ( String d e s c r i p t i o n ) {
5 this . description = description ;
}
7
p u b l i c v o i d up ( ) {
9 System . o u t . p r i n t l n ( d e s c r i p t i o n + " g o i n g up " ) ;
}
11
p u b l i c v o i d down ( ) {
13 System . o u t . p r i n t l n ( d e s c r i p t i o n + " g o i n g down " ) ;
}
15
public String toString () {
17 return description ;
}
19 }

80 186
Facade Code

1 public class Projector {


private String description ;
3 p r i v a t e DvdPlayer dvdPlayer ;

5 p u b l i c P r o j e c t o r ( S t r i n g d e s c r i p t i o n , DvdPlayer dvdPlayer ) {
this . description = description ;
7 t h i s . dvdPlayer = dvdPlayer ;
}
9
p u b l i c v o i d on ( ) {
11 System . o u t . p r i n t l n ( d e s c r i p t i o n + " on " ) ;
}
13
public void o f f ( ) {
15 System . o u t . p r i n t l n ( d e s c r i p t i o n + " o f f " ) ;
}
17
p u b l i c v o i d wideScreenMode ( ) {
19 System . o u t . p r i n t l n ( d e s c r i p t i o n + " i n w i d e s c r e e n mode ( 1 6 x9 a s p e c t r a t i o ) " ) ;
}
21
...
23 }

81 186
Facade Code

1 public class TheaterLights {


String description ;
3
public TheaterLights ( String description ) {
5 this . description = description ;
}
7
p u b l i c v o i d on ( ) {
9 System . o u t . p r i n t l n ( d e s c r i p t i o n + " on " ) ;
}
11
public void o f f ( ) {
13 System . o u t . p r i n t l n ( d e s c r i p t i o n + " o f f " ) ;
}
15
p u b l i c v o i d dim ( i n t l e v e l ) {
17 System . o u t . p r i n t l n ( d e s c r i p t i o n + " dimming t o " + l e v e l + "%" ) ;
}
19
public String toString () {
21 return description ;
}
23 }

82 186
Facade Code

1 p u b l i c c l a s s HomeTheaterFacade {
p r i v a t e A m p l i f i e r amp ;
3 p r i v a t e Tuner t u n e r ;
p r i v a t e D v d P l a y e r dvd ;
5 p r i v a t e C d P l a y e r cd ;
private Projector projector ;
7 private TheaterLights lights ;
p r i v a t e Screen screen ;
9 p r i v a t e PopcornPopper popper ;

11 p u b l i c HomeTheaterFacade ( A m p l i f i e r amp ,
Tuner t u n e r ,
13 D v d P l a y e r dvd ,
C d P l a y e r cd ,
15 Projector projector ,
Screen screen ,
17 TheaterLights lights ,
PopcornPopper popper ) {
19 t h i s . amp = amp ;
t h i s . tuner = tuner ;
21 t h i s . dvd = dvd ;
...
23 }

83 186
Facade Code

1 p u b l i c v o i d watchMovie ( S t r i n g movie ) { 1 p u b l i c v o i d endMovie ( ) {


System . o u t . p r i n t l n ( " Get r e a d y t o System . o u t . p r i n t l n ( " S h u t t i n g
,→ watch a movie . . . " ) ; ,→ movie t h e a t e r down . . . " ) ;
3 p o p p e r . on ( ) ; 3 popper . o f f ( ) ;
p o p p e r . pop ( ) ; l i g h t s . on ( ) ;
5 l i g h t s . dim ( 1 0 ) ; 5 s c r e e n . up ( ) ;
s c r e e n . down ( ) ; projector . off () ;
7 p r o j e c t o r . on ( ) ; 7 amp . o f f ( ) ;
p r o j e c t o r . wideScreenMode ( ) ; dvd . s t o p ( ) ;
9 amp . on ( ) ; 9 dvd . e j e c t ( ) ;
amp . s e t D v d ( dvd ) ; dvd . o f f ( ) ;
11 amp . s e t S u r r o u n d S o u n d ( ) ; 11 }
amp . s e t V o l u m e ( 5 ) ;
13 dvd . on ( ) ;
dvd . p l a y ( movie ) ;
15 }

84 186
Facade Code

1 p u b l i c c l a s s HomeTheaterTestDrive {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 / / I n i t i a l i z e subsystems
A m p l i f i e r amp = new A m p l i f i e r ( " Top −O− L i n e A m p l i f i e r " ) ;
5 Tuner t u n e r = new Tuner ( " Top −O− L i n e AM/FM Tuner " , amp ) ;
D v d P l a y e r dvd = new D v d P l a y e r ( " Top −O− L i n e DVD P l a y e r " , amp ) ;
7 C d P l a y e r cd = new C d P l a y e r ( " Top −O− L i n e CD P l a y e r " , amp ) ;
P r o j e c t o r p r o j e c t o r = new P r o j e c t o r ( " Top −O− L i n e P r o j e c t o r " , dvd ) ;
9 T h e a t e r L i g h t s l i g h t s = new T h e a t e r L i g h t s ( " T h e a t e r C e i l i n g L i g h t s " ) ;
S c r e e n s c r e e n = new S c r e e n ( " T h e a t e r S c r e e n " ) ;
11 P o p c o r n P o p p e r p o p p e r = new P o p c o r n P o p p e r ( " Po pco rn Popper " ) ;

13 HomeTheaterFacade homeTheater = new HomeTheaterFacade ( amp , t u n e r , dvd , cd ,


,→ p r o j e c t o r , s c r e e n , l i g h t s , p o p p e r ) ;

15 homeTheater . watchMovie ( " R a i d e r s o f t h e L o s t Ark " ) ;


homeTheater . endMovie ( ) ;
17 }
}

85 186
Definition of Facade Pattern

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

There can be significant benefit in wrapping a complex subsystem with a simplified


interface.
▶ If you don’t need the advanced functionality or fine-grained control of the former, the latter
makes life easy.
Façade works best when you are accessing a subset of the system’s functionality.
▶ You can add new features by adding them to the Façade (not the subsystem); you still get a
simpler interface.
Client code is simplified and dependencies are reduced.
▶ A Façade not only simplifies an interface, it decouples a client from a subsystem of
components
Indeed, Façade lets us encapsulate subsystems, hiding them from the rest of the system.
86 186
Structure of Facade Pattern

87 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

88 186
Weather Monitoring Example

We need to pull information from the station and then generate "Current Conditions,
Weather Statistics, and a Weather Forecast".

89 186
WeatherData Skeleton

We receive a partial implementation of the WeatherData class from our client.


▶ They provide three getter methods for the sensor values and an empty
measurementsChanged() method that is guaranteed to be called whenever a sensor provides a
new value.
▶ We need to pass these values to our three displays. . . so that’s simple!

90 186
Without Design Pattern

Problems?
The number and type of displays
p u l i c c l a s s WeatherData {
2 // instance variable declarations may vary.
4 public v o i d measurementsChanged ( ) { ▶ These three displays are hard
float temp = g e t T e m p e r a t u r e ( ) ;
6 float humidity = getHumidity ( ) ; coded with no easy way to
float pressure = getPressure ( ) ; update them.
8
c u r r e n t C o n d i t i o n s D i s p l a y . u p d a t e ( temp ,
10 humidity , Coding to implementations, not
pressure ) ;
12 s t a t i s t i c s D i s p l a y . u p d a t e ( temp , an interface!
humidity ,
14 pressure ) ; ▶ Each implementation has
f o r e c a s t D i s p l a y . u p d a t e ( temp , adopted the same interface, so
16 humidity ,
pressure ) ; this will make translation easy!
18 }

20 / / Other WeatherData methods h e r e Solution:


}
This situation can benefit from
use of the observer pattern.

91 186
Observer Pattern Explained

This pattern is similar to subscribing to a hard copy newspaper.


▶ A newspaper comes into existence and starts publishing editions.
▶ You become interested in the newspaper and subscribe to it.
▶ Any time an edition becomes available, you are notified (by the fact that it is delivered to you).
▶ When you don’t want the paper anymore, you unsubscribe.
▶ The newspaper’s current set of subscribers can change at any time.

Observer is just like this but we call the publisher the "subject" and we refer to subscribers
as "observers".

92 186
Observer In Action

93 186
Observer In Action

94 186
Observer In Action

95 186
Observer In Action

96 186
Definition of Observer Pattern

Observer Pattern
The Observer Pattern defines a one-to-many dependency between a set of objects, such that
when one object (the subject) changes all of its dependents (observers) are notified and
updated automatically.

Don’t miss out when something interesting (in your system) happens!.
▶ The Observer Pattern allows objects to keep other objects informed about events occurring
within a software system (or across multiple systems).
▶ It’s dynamic in that an object can choose to receive or not receive notifications at runtime.
▶ Observer happens to be one of the most heavily used patterns in the Java Development Kit.

- And indeed is present in many frameworks.

97 186
Structure of Observer Pattern

98 186
Observer Pattern

Observer affords a loosely coupled interaction between subject and observer.


▶ This means they can interact with very little knowledge about each other.

The subject only knows that observers implement the Observer interface.
▶ We can add/remove observers of any type at any time.
▶ We never have to modify subject to add a new type of observer.

We can reuse subjects and observers in other contexts.


▶ The interfaces plug-and-play anywhere observer is used.

Observers may have to know about the ConcreteSubject class if it provides many different
state-related methods.
▶ Otherwise, data can be passed to observers via the update() method.

99 186
Observer Pattern Code

1 public interface Subject {


p u b l i c void r e g i s t e r O b s e r v e r ( Observer observer ) ;
3 p u b l i c void removeObserver ( Observer o b s e r v e r ) ;
public void notifyObservers ( ) ;
5 }

7
p u b l i c i n t e r f a c e Observer {
9 p u b l i c v o i d u p d a t e ( f l o a t temp , f l o a t h u m i d i t y , f l o a t p r e s s u r e ) ;
}
11

13 public i n t e r f a c e DisplayElement {
public void display ( ) ;
15 }

100 186
Observer Pattern Code

1 p u b l i c c l a s s WeatherData i m p l e m e n t s S u b j e c t {
p r i v a t e L i s t < Observer > o b s e r v e r s ;
3 p r i v a t e f l o a t temperature ;
p r i v a t e f l o a t humidity ;
5 private float pressure ;

7 p u b l i c WeatherData ( ) {
o b s e r v e r s = new A r r a y L i s t < > ( ) ;
9 }

11 p u b l i c void r e g i s t e r O b s e r v e r ( Observer observer ) {


o b s e r v e r s . add ( o b s e r v e r ) ;
13 }

15 p u b l i c void removeObserver ( Observer o b s e r v e r ) {


o b s e r v e r s . remove ( o b s e r v e r ) ;
17 }

19 public void notifyObservers ( ) {


f o r ( Observer observer : observers ) {
21 o b s e r v e r . update ( temperature , humidity , p r e s s u r e ) ;
}
23 }

101 186
Observer Pattern Code

1 p u b l i c v o i d measurementsChanged ( ) {
notifyObservers ( ) ;
3 }

5 p u b l i c void setMeasurements ( f l o a t temperature , f l o a t humidity , f l o a t p r e s s u r e ) {


t h i s . temperature = temperature ;
7 t h i s . humidity = humidity ;
this . pressure = pressure ;
9 measurementsChanged ( ) ;
}
11
p u b l i c f l o a t getTemperature ( ) {
13 return temperature ;
}
15
p u b l i c f l o a t getHumidity ( ) {
17 r e t ur n humidity ;
}
19
public float getPressure ( ) {
21 return pressure ;
}
23 }

102 186
Observer Pattern Code

1 p u b l i c c l a s s F o r e c a s t D i s p l a y implements Observer , DisplayElement {


private float currentPressure ;
3 private float lastPressure ;
p r i v a t e WeatherData w e a t h e r D a t a ;
5
p u b l i c F o r e c a s t D i s p l a y ( WeatherData w e a t h e r D a t a ) {
7 t h i s . weatherData = weatherData ;
weatherData . r e g i s t e r O b s e r v e r ( t h i s ) ;
9 }

11 p u b l i c v o i d u p d a t e ( f l o a t temp , f l o a t h u m i d i t y , f l o a t p r e s s u r e ) {
lastPressure = currentPressure ;
13 currentPressure = pressure ;
display () ;
15 }

17 public void display ( ) {


i f ( F l o a t . compare ( c u r r e n t P r e s s u r e , l a s t P r e s s u r e ) > 0 ) {
19 System . o u t . p r i n t l n ( " I m p r o v i n g w e a t h e r on t h e way ! " ) ;
} e l s e i f ( F l o a t . compare ( c u r r e n t P r e s s u r e , l a s t P r e s s u r e ) < 0 ) {
21 System . o u t . p r i n t l n ( " Watch o u t f o r c o o l e r , r a i n y w e a t h e r " ) ;
}
23 }
}

103 186
Observer Pattern Code

p u b l i c c l a s s S t a t i s t i c s D i s p l a y implements Observer , DisplayElement {


2 p r i v a t e f l o a t maxTemp ;
p r i v a t e f l o a t minTemp ;
4 p r i v a t e f l o a t tempSum ;
p r i v a t e i n t numReadings ;
6 p r i v a t e WeatherData w e a t h e r D a t a ;

8 p u b l i c S t a t i s t i c s D i s p l a y ( WeatherData w e a t h e r D a t a ) { ... }

10 p u b l i c v o i d u p d a t e ( f l o a t temp , f l o a t h u m i d i t y , f l o a t p r e s s u r e ) {
tempSum += temp ;
12 numReadings + + ;
i f ( temp > maxTemp ) maxTemp = temp ;
14 i f ( temp < minTemp ) minTemp = temp ;
display () ;
16 }

18 public void display ( ) {


System . o u t . p r i n t l n ( " Avg / Max / Min t e m p e r a t u r e = " + ( tempSum / numReadings )
20 + " / " + maxTemp + " / " + minTemp ) ;
}
22 }

104 186
Observer Pattern Code

public c l a s s WeatherStation {
2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
WeatherData w e a t h e r D a t a = new WeatherData ( ) ;
4
C u r r e n t C o n d i t i o n s D i s p l a y c u r r e n t D i s p l a y = new C u r r e n t C o n d i t i o n s D i s p l a y ( w e a t h e r D a t a ) ;
6 S t a t i s t i c s D i s p l a y s t a t i s t i c s D i s p l a y = new S t a t i s t i c s D i s p l a y ( w e a t h e r D a t a ) ;
F o r e c a s t D i s p l a y f o r e c a s t D i s p l a y = new F o r e c a s t D i s p l a y ( w e a t h e r D a t a ) ;
8
System . o u t . p r i n t l n ( " −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− " ) ;
10 weatherData . setMeasurements ( 8 0 , 65 , 3 0 . 4 f ) ;

12 System . o u t . p r i n t l n ( " −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− " ) ;


weatherData . setMeasurements ( 8 2 , 70 , 2 9 . 2 f ) ;
14
System . o u t . p r i n t l n ( " −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− " ) ;
16 weatherData . setMeasurements ( 7 8 , 90 , 2 9 . 2 f ) ;
System . o u t . p r i n t l n ( " −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− " ) ;
18 }
}

105 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

106 186
Example: Tea and Coffee

Consider an example in which we have recipes for making tea and coffee at a coffee shop.

Coffee Tea
1. Boil water 1. Boil water
2. Brew coffee in boiling water 2. Steep tea in boiling water
3. Pour coffee in cup 3. Pour tea in cup
4. Add sugar and milk 4. Add lemon

107 186
Coffee class for making coffee

The prepareRecipe() method


is our recipe for coffee,
1 public c l a s s Coffee {
public void prepareRecipe ( ) { straight out of the training
3 boilWater ( ) ;
brewCoffeeGrinds ( ) ; manual.
5 pourInCup ( ) ;
addSugarAndMilk ( ) ; ▶ Each of the steps is
7 }
implemented as a
9 public void boilWater ( ) { separate method.
System . o u t . p r i n t l n ( " B o i l i n g w a t e r " ) ;
11 }

13 public void brewCoffeeGrinds ( ) {


Each of these methods
System . o u t . p r i n t l n ( " D r i p p i n g C o f f e e t h r o u g h f i l t e r " ) ; implements one step of the
15 }
algorithm.
17 p u b l i c v o i d pourInCup ( ) {
System . o u t . p r i n t l n ( " P o u r i n g i n t o cup " ) ; ▶ There’s a method to boil
19 }
water, brew the coffee,
21 p u b l i c v o i d addSugarAndMilk ( ) {
System . o u t . p r i n t l n ( " Adding S u g a r and Milk " ) ; pour the coffee in a cup
23 } and add sugar and milk.
}

108 186
Tea class for making tea

The prepareRecipe() method


looks very similar to the one
p u b l i c c l a s s Tea {
2 public void prepareRecipe ( ) { we just implemented in
boilWater ( ) ;
4 steepTeaBag ( ) ; Coffee; the second and forth
6
pourInCup ( ) ;
addLemon ( ) ;
steps are different, but it’s
} basically the same recipe.
8
public void boilWater ( ) {
10 System . o u t . p r i n t l n ( " B o i l i n g w a t e r " ) ; ▶ These two methods are
} specialized to Tea.
12
p u b l i c void steepTeaBag ( ) {
14
}
System . o u t . p r i n t l n ( " S t e e p i n g t h e t e a " ) ;
Notice that the first and
16 third methods are exactly
p u b l i c v o i d addLemon ( ) {
18 System . o u t . p r i n t l n ( " Adding Lemon " ) ; the same as they are in
}
20 Coffee! So we definitely
p u b l i c v o i d pourInCup ( ) {
22 System . o u t . p r i n t l n ( " P o u r i n g i n t o cup " ) ;
have some code duplication
24 }
} going on here.

109 186
Code Duplication!

We have code duplication occurring in these two classes.


▶ boilWater() and pourInCup() are exactly the same.

Lets get rid of the duplication.

110 186
Abstract classes Coffee, Tea

111 186
Similar algorithms

The structure of the algorithms in prepareRecipe() is similar for Tea and Coffee.
▶ We can improve our code further by making the code in prepareRecipe() more abstract.
brewCoffeeGrinds() and steepTea() -> brew()
addSugarAndMilk() and addLemon() -> addCondiments()

Now all we need to do is specify this structure in [Link]() and


make sure we do it in such a way so that subclasses can’t change the structure.
▶ By using the word "final".

112 186
Similar algorithms

Because Coffee and Tea handle


these methods in different
public abstract class CaffeineBeverage { ways, they’re going to have to
2 p u b l i c final v o i d p r e p a r e R e c i p e ( ) {
boilWater ( ) ; be declared as abstract. Let the
4 brew ( ) ; subclasses worry about that
pourInCup ( ) ;
6 addCondiments ( ) ; stuff!
}
8 brew() and addCondiments()
p u b l i c abstract v o i d brew ( ) ;
10 p u b l i c abstract v o i d addCondiments ( ) ;
are abstract and must be
supplied by subclasses.
12 public void boilWater ( ) {
System . o u t . p r i n t l n ( " B o i l i n g w a t e r " ) ;
14 }
boilWater() and pourInCup()
are specified and shared across
16 p u b l i c v o i d pourInCup ( ) { all subclasses.
System . o u t . p r i n t l n ( " P o u r i n g i n t o cup " ) ;
18 }
}

113 186
Dealing with the Coffee and Tea classes

Coffee and Tea now extend


CaffeineBeverage.
1 public c l a s s Coffee extends CaffeineBeverage {
p u b l i c v o i d brew ( ) {
3 System . o u t . p r i n t l n ( " D r i p p i n g C o f f e e t h r o u g h f i l t e r " ) ; Coffee and Tea need to
}
5 define brew() and
7
p u b l i c v o i d addCondiments ( ) {
System . o u t . p r i n t l n ( " Adding S u g a r and Milk " ) ;
addCondiments() - the two
} abstract methods from
9 }
CaffeineBeverage.
11
p u b l i c c l a s s Tea e x t e n d s C a f f e i n e B e v e r a g e {
13 p u b l i c v o i d brew ( ) { boilWater() and pourInCup()
System . o u t . p r i n t l n ( " S t e e p i n g t h e t e a " ) ;
15 } are specified and shared
17 p u b l i c v o i d addCondiments ( ) {
across all subclasses.
System . o u t . p r i n t l n ( " Adding Lemon " ) ;
19 }
}

114 186
What have we done?

Took two separate classes with separate but similar algorithms.


Noticed duplication and eliminated it by adding a superclass.
Made steps of algorithm more abstract and specified its structure in the superclass.
▶ Thereby eliminating another "implicit" duplication between the two classes.

Revised subclasses to implement the abstract (unspecified) portions of the algorithm. . . in


a way that made sense for them.

115 186
Definition of Template Method Pattern

Template Method Pattern


The 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.

Template Method defines the steps of an algorithm and allows subclasses to provide the
implementation for one or more steps.
▶ Makes the algorithm abstract.
- Each step of the algorithm is represented by a method.
▶ Encapsulates the details of most steps.
- Steps (methods) handled by subclasses are declared abstract.
- Shared steps (concrete methods) are placed in the same class that has the template method,
allowing for code re-use among the various subclasses.

This ensures the algorithm’s structure stays unchanged, while subclasses provide some
part of the implementation.
116 186
Structure of Template Method

117 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

118 186
Example: Starbuzz Coffee

Under pressure to update their "point of sale" system to keep up with their expanding set
of beverage products.

▶ Started with a Beverage abstract base class and four implementations: HouseBlend,
DarkRoast, Decaf, and Espresso.
- Each beverage can provide a description and compute its cost.

▶ But they also offer a range of condiments including: steamed milk, soy, and mocha.

- These condiments alter a beverage’s description and cost.


- The use of the word "alter" here is key since it provides a hint that we might be able to use the
Decorator Pattern.

With inheritance on your brain, you may add condiments to this design in one of two ways.
▶ One subclass per combination of condiment.
▶ Add condiment handling to the Beverage superclass.

119 186
Example: Initial Starbuzz System
When they fi rst went into business they designed their classes like this...

120 186
Approach One: One Subclass per Combination

This is incomplete, but you can see the problem ...


121 186
Approach Two: Let Beverage Handle Condiments

We have a problem
This assumes that all
concrete Beverage
classes need these
condiments.
Condiments may
vary (old ones go, new
ones are added, price
changes occur, etc.),
shouldn’t Beverage
be encapsulated from
this some how?
What if a customer
wants a double
mocha?

122 186
StarBuzz Using Decorators

123 186
Decorator Pattern Code

p u b l i c a b s t r a c t c l a s s Beverage {
2 p r o t e c t e d S t r i n g d e s c r i p t i o n = " Unknown B e v e r a g e " ;

4 public String getDescription () {


return description ;
6 }

8 p u b l i c a b s t r a c t double cost ( ) ;
}
10
p u b l i c a b s t r a c t c l a s s CondimentDecorator extends Beverage {
12 protected Beverage beverage ;

14 p u b l i c CondimentDecorator ( Beverage beverage ) {


t h i s . beverage = beverage ;
16 }

18 public abstract String getDescription () ;


}

124 186
Decorator Pattern Code

1 p u b l i c c l a s s Espresso extends Beverage {


public Espresso ( ) {
3 this . description = " Espresso " ;
}
5
p u b l i c double cost ( ) {
7 return 1 . 9 9 ;
}
9 }

11 p u b l i c c l a s s HouseBlend e x t e n d s B e v e r a g e {
p u b l i c HouseBlend ( ) {
13 t h i s . d e s c r i p t i o n = " House B l e n d C o f f e e " ;
}
15
p u b l i c double cost ( ) {
17 return 0 . 8 9 ;
}
19 }

125 186
Decorator Pattern Code

1 p u b l i c c l a s s DarkRoast extends Beverage {


p u b l i c DarkRoast ( ) {
3 t h i s . d e s c r i p t i o n = " Dark R o a s t C o f f e e " ;
}
5
p u b l i c double cost ( ) {
7 return 0 . 9 9 ;
}
9 }

11 p u b l i c c l a s s Decaf extends Beverage {


p u b l i c Decaf ( ) {
13 t h i s . d e s c r i p t i o n = " Decaf Coffee " ;
}
15
p u b l i c double cost ( ) {
17 return 1 . 0 5 ;
}
19 }

126 186
Decorator Pattern Code

1 p u b l i c c l a s s Mocha e x t e n d s C o n d i m e n t D e c o r a t o r {
p u b l i c Mocha ( B e v e r a g e b e v e r a g e ) {
3 super ( beverage } ;
}
5
public String getDescription () {
7 r e t u r n b e v e r a g e . g e t D e s c r i p t i o n ( ) + " , Mocha " ;
}
9
p u b l i c double cost ( ) {
11 return 0.20 + beverage . cost ( ) ;
}
13 }

127 186
Decorator Pattern Code

1 p u b l i c c l a s s Soy e x t e n d s C o n d i m e n t D e c o r a t o r {
p u b l i c Soy ( B e v e r a g e b e v e r a g e ) {
3 super ( beverage } ;
}
5
public String getDescription () {
7 r e t u r n b e v e r a g e . g e t D e s c r i p t i o n ( ) + " , Soy " ;
}
9
p u b l i c double cost ( ) {
11 return 0.15 + beverage . cost ( ) ;
}
13 }

128 186
Decorator Pattern Code

1 p u b l i c c l a s s Whip e x t e n d s C o n d i m e n t D e c o r a t o r {
p u b l i c Whip ( B e v e r a g e b e v e r a g e ) {
3 super ( beverage } ;
}
5
public String getDescription () {
7 r e t u r n b e v e r a g e . g e t D e s c r i p t i o n ( ) + " , Whip " ;
}
9
p u b l i c double cost ( ) {
11 return 0.10 + beverage . cost ( ) ;
}
13 }

129 186
Decorator Pattern Code

1 p u b l i c c l a s s Milk ext ends CondimentDecorator {


p u b l i c Milk ( Beverage beverage ) {
3 super ( beverage } ;
}
5
public String getDescription () {
7 r e t u r n beverage . g e t D e s c r i p t i o n ( ) + " , Milk " ;
}
9
p u b l i c double cost ( ) {
11 return 0.10 + beverage . cost ( ) ;
}
13 }

130 186
Decorator Pattern Code

1 public class StarbuzzCoffee {


p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
3 B e v e r a g e b e v e r a g e = new E s p r e s s o ( ) ;
System . o u t . p r i n t l n ( b e v e r a g e . g e t D e s c r i p t i o n ( ) + " $ " + b e v e r a g e . c o s t ( ) ) ;
5
/ / Make a D a r k R o a s t o b j e c t
7 B e v e r a g e b e v e r a g e 2 = new D a r k R o a s t ( ) ;
/ / Wrap i t w i t h a Mocha .
9 b e v e r a g e 2 = new Mocha ( b e v e r a g e 2 ) ;
/ / Wrap i t i n a s e c o n d Mocha
11 b e v e r a g e 2 = new Mocha ( b e v e r a g e 2 ) ;
/ / Wrap i t i n a Whip
13 b e v e r a g e 2 = new Whip ( b e v e r a g e 2 ) ;
System . o u t . p r i n t l n ( b e v e r a g e 2 . g e t D e s c r i p t i o n ( ) + " $ " + b e v e r a g e 2 . c o s t ( ) ) ;
15
B e v e r a g e b e v e r a g e 3 = new HouseBlend ( ) ;
17 b e v e r a g e 3 = new Soy ( b e v e r a g e 3 ) ;
b e v e r a g e 3 = new Mocha ( b e v e r a g e 3 ) ;
19 b e v e r a g e 3 = new Whip ( b e v e r a g e 3 ) ;
System . o u t . p r i n t l n ( b e v e r a g e 3 . g e t D e s c r i p t i o n ( ) + " $ " + b e v e r a g e 3 . c o s t ( ) ) ;
21 }
}

131 186
Definition of Decorator Pattern

Decorator Pattern
The Decorator Pattern is a design pattern that allows behavior to be added to an individual
object, dynamically, without affecting the behavior of other objects from the same class.

The Decorator Pattern provides a powerful mechanism for adding new behaviors to an
object at runtime.
▶ The mechanism is based on the notion of "wrapping" which is just a fancy way of saying
"delegation" but with the added twist that the delegator and the delegate both implement the
same interface.
The decorator pattern provides yet another way in which a class’s runtime behavior can be
extended without requiring modification to the class.
▶ This supports the goal of the Open-Closed Principle: Classes should be open for extension
but closed to modification.
- Inheritance is one way to do this, but composition and delegation are more flexible (and
Decorator takes advantage of delegation).
- As the Gang of Four put it: "Decorator lets you attach additional responsibilities to an object
dynamically. Decorators provide a flexible alternative to subclassing for extending functionality."

132 186
Structure of Decorator Pattern

133 186
Client Perspective

134 186
Real-World Decorators: Java I/O

135 186
The Textbook’s Take

As we saw, Decorator offers another solution to the problem of rapidly multiplying


combinations of subclasses.
▶ We saw examples of other solutions when we made use of the Strategy Pattern and the Bridge
Pattern.
The Decorator Pattern provides a means for creating different combinations of
functionality by creating chains in which each member of the chain can augment or
"decorate" the output of the previous member.
▶ Plus, it separates the step of building these chains from the use of these chains.

The Decorator Pattern comes into play when there are a variety of optional functions
that can precede or follow another function that is always executed.
This is a very powerful idea that can be implemented in a variety of ways.
▶ The fact that all of the classes in the decorator pattern hide behind the abstraction of
Component enables all of the good benefits of OO design discussed previously.

136 186
Presentation Outline
1 Motivations
2 Introduction to Design Patterns
3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Simple Factory
Factory Method
Abstract Factory
Iterator Pattern
4 References

137 186
The Problem with "new"

When you use new you are certainly instantiating a concrete class, so that’s definitely an
implementation, not an interface.

Duck duck ;
2 if ( picnic ) {
duck = new M a l l a r D u c k ( ) ;
4 } e l s e i f ( huntin ) {
duck = new DecoyDuck ( ) ;
6 } else {
duck = new RubberDuck ( ) ;
8 }

When you see code like this, you know that when it comes time for changes or extensions,
you’ll have to reopen this code and examine what needs to be added (or deleted). Often
this kind of code ends up in several parts of the application making maintenance and
updates more difficult and error-prone.
138 186
PizzaStore Example

We have a pizza store program


that wants to separate the
public class PizzaStore { process of creating a pizza from
2 p u b l i c Pizza o r d e r P i z z a ( S t r i n g type ) {
Pizza pizza ; the process of preparing /
4 i f ( type . equals ( " cheese " ) ) { ordering a pizza.
p i z z a = new C h e e s e P i z z a ( ) ;
6 } e l s e i f ( type . equals ( " greek " ) ) { ▶ This code is an excellent
p i z z a = new G r e e k P i z z a ( ) ;
8 } e l s e i f ( type . equals ( " pepperoni " ) ) {
example of "coding to an
p i z z a = new P e p p e r o n i P i z z a ( ) ; interface",
10 }
▶ But, it is NOT closed for
12 pizza . prepare ( ) ; modification. If the Pizza store
p i z z a . bake ( ) ; changes its pizza offerings, we
14 pizza . cut ( ) ;
p i z z a . box ( ) ;
have to open this code and
16 return pizza ; modify it.
}
18 }

139 186
Encapsulate Creation Code

A simple way to encapsulate the


code of pizza creation and move it
public class PizzaStore {
2 / / A r e f e r e n c e to a SimplePizzaFactory .
out into another object that is only
4
private SimplePizzaFactory factory ; going to be concerned with
public PizzaStore ( SimplePizzaFactory factory ) { creating pizzas.
6 / / The f a c t o r y p a s s e d t o i t i n t h e c o n s t r u c t o r .
this . factory = factory ;
8 }
▶ That new class depends on the
concrete classes, but those
10 p u b l i c Pizza o r d e r P i z z a ( S t r i n g type ) {
/ / U s i n g t h e f a c t o r y t o c r e a t e i t s p i z z a s by dependencies no longer impact
12 // s i m p l y p a s s i n g on t h e t y p e o f t h e o r d e r . the preparation code.
Pizza pizza = [Link](type);
14
pizza . prepare ( ) ;
16 pizza . bake ( ) ;
pizza . cut ( ) ;
18 pizza . box ( ) ;

20 return pizza ;
}
22 }

140 186
Encapsulate Creation Code

The new object is called a Factory.

public class SimplePizzaFactory {


Factories handle the details of
2 p u b l i c Pizza c r e a t e P i z z a ( S t r i n g type ) { object creation. Once we have a
i f ( type . equals ( " cheese " ) ) SimplePizzaFactory, our
4 r e t u r n new C h e e s e P i z z a ( ) ;
orderPizza() method becomes a
6 i f ( type . equals ( " greek " ) ) { client of that object. Anytime it
r e t u r n new G r e e k P i z z a ( ) ;
8
needs a pizza, it asks the pizza
i f ( type . equals ( " pepperoni " ) ) { factory to make one.
10 r e t u r n new P e p p e r o n i P i z z a ( ) ;
Now the orderPizza() method just
12 i f ( t y p e . e q u a l s ( " clam " ) ) {
r e t u r n new C l a m P i z z a ( ) ; cares that it gets a pizza that
14 implements the Pizza interface so
return null ;
16 }
that it can call prepare(), bake(),
} cut(), and box().

141 186
Let’s implement Pizza!

1 public abstract class Pizza {


p r o t e c t e d S t r i n g name ;
3 p r o t e c t e d S t r i n g dough ;
protected S t r i n g sauce ;
5 protected List < String > toppings ;

7 public Pizza ( ) {
t h i s . t o p p i n g s = new A r r a y L i s t < > ( ) ;
9 }

11 p u b l i c S t r i n g getName ( ) {
r e t u r n name ;
13 }

15 public void prepare ( ) {


System . o u t . p r i n t l n ( " P r e p a r i n g " + name ) ;
17 }

19 p u b l i c v o i d bake ( ) {
System . o u t . p r i n t l n ( " Bak ing " + name ) ;
21 }

142 186
Let’s implement Pizza!

1 public void cut ( ) {


System . o u t . p r i n t l n ( " C u t t i n g " + name ) ;
3 }

5 p u b l i c v o i d box ( ) {
System . o u t . p r i n t l n ( " B o x i n g " + name ) ;
7 }

9 public String toString () {


/ / Code t o d i s p l a y p i z z a name and i n g r e d i e n t s
11 S t r i n g B u i l d e r d i s p l a y = new S t r i n g B u i l d e r ( ) ;
d i s p l a y . append ( " −−−− " + name + " − − − −\n " ) ;
13 d i s p l a y . append ( dough + " \ n " ) ;
d i s p l a y . append ( s a u c e + " \ n " ) ;
15 for ( String topping : toppings ) {
d i s p l a y . append ( t o p p i n g + " \ n " ) ;
17 }

19 return display . toString ( ) ;


}
21 }

143 186
Let’s implement Pizza!

1 public c l a s s CheesePizza extends Pizza {


public CheesePizza ( ) {
3 t h i s . name = " Cheese P i z z a " ;
t h i s . dough = " R e g u l a r C r u s t " ;
5 t h i s . s a u c e = " M a r i n a r a P i z z a Sauce " ;
t h i s . t o p p i n g s . add ( " F r e s h M o z z a r e l l a " ) ;
7 t h i s . t o p p i n g s . add ( " Parmesan " ) ;
}
9 }

11
public c l a s s PepperoniPizza extends Pizza {
13 public PepperoniPizza ( ) {
t h i s . name = " P e p p e r o n i P i z z a " ;
15 t h i s . dough = " C r u s t " ;
t h i s . sauce = " Marinara sauce " ;
17 t h i s . t o p p i n g s . add ( " S l i c e d P e p p e r o n i " ) ;
t h i s . t o p p i n g s . add ( " S l i c e d Onion " ) ;
19 t h i s . t o p p i n g s . add ( " G r a t e d parmesan c h e e s e " ) ;
}
21 }

23 ...

144 186
Simple Pizza Demonstration

1 public class SimplePizzaTestDrive {


p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 S i m p l e P i z z a F a c t o r y f a c t o r y = new S i m p l e P i z z a F a c t o r y ( ) ;
P i z z a S t o r e s t o r e = new P i z z a S t o r e ( f a c t o r y ) ;
5
Pizza pizza = store . orderPizza ( " cheese " ) ;
7 System . o u t . p r i n t l n ( "We o r d e r e d a " + p i z z a . getName ( ) + " \ n " ) ;

9 pizza = store . orderPizza ( " veggie " ) ;


System . o u t . p r i n t l n ( "We o r d e r e d a " + p i z z a . getName ( ) + " \ n " ) ;
11 }
}

145 186
Encapsulate Creation Code

While this is nice, it is not as flexible as it can be. To increase flexibility we need to look at
two design patterns: Factory Method and Abstract Factory.

146 186
Franchising the pizza store

What about regional differences? Each franchise might want to offer different styles of
pizzas (New York, Chicago, and California, to name a few), depending on where the
franchise store is located and the tastes of the local pizza connoisseurs.

147 186
Encapsulate Creation Code

What varies among the regional PizzaStores is the style of pizzas they make. We can push
all these variations into the createPizza() method and make it responsible for creating the
right kind of pizza.

148 186
A framework for the pizza store

This class is a (very simple) OO


framework. The framework provides
public abstract class PizzaStore { one service: "order Pizza".
2 protected abstract Pizza createPizza(String type);
The framework invokes the
4 p u b l i c Pizza o r d e r P i z z a ( S t r i n g type ) {
Pizza pizza = createPizza(type); createPizza() factory method to
6 create a pizza that it can then prepare
pizza . prepare ( ) ;
8 pizza . bake ( ) ; using a well-defined, consistent
pizza . cut ( ) ; process.
10 pizza . box ( ) ;
A "client" of the framework will
12 return pizza ;
} subclass this class and provide an
14 } implementation of the createPizza()
method.

149 186
Let’s make a PizzaStore

Nice and simple. If you want a


NY-style Pizza, you create an
public c l a s s NYPizzaStore extends PizzaStore { instance of this class and call
2 public Pizza createPizza ( String style ) {
i f ( s t y l e . equals ( " cheese " ) ) orderPizza() passing in the type.
4 r e t u r n new N Y S t y l e C h e e s e P i z z a ( ) ; The subclass makes sure that
6 i f ( style . equals ( " veggie " ) ) the pizza is created using the
r e t u r n new N Y S t y l e V e g g i e P i z z a ( ) ; correct style.
8
i f ( s t y l e . e q u a l s ( " clam " ) )
10 r e t u r n new N Y S t y l e C l a m P i z z a ( ) ;

12 i f ( s t y l e . equals ( " pepperoni " ) )


r e t u r n new N Y S t y l e P e p p e r o n i P i z z a ( ) ;
14 }

16 return null ;
}
18 }

150 186
Chicago Pizza Store

If you need a different


style, create a new
public c l a s s ChicagoPizzaStore extends PizzaStore { subclass.
2 public Pizza createPizza ( String style ) {
i f ( s t y l e . equals ( " cheese " ) )
4 r e t u r n new C h i c a g o S t y l e C h e e s e P i z z a ( ) ;

6 i f ( style . equals ( " veggie " ) )


r e t u r n new C h i c a g o S t y l e V e g g i e P i z z a ( ) ;
8
i f ( s t y l e . e q u a l s ( " clam " ) )
10 r e t u r n new C h i c a g o S t y l e C l a m P i z z a ( ) ;

12 i f ( s t y l e . equals ( " pepperoni " ) )


r e t u r n new C h i c a g o S t y l e P e p p e r o n i P i z z a ( ) ;
14
return null ;
16 }
}

151 186
A couple of the concrete product classes

1 public c l a s s NYStylePepperoniPizza extends Pizza {


public NYStylePepperoniPizza ( ) {
3 t h i s . name = "NY S t y l e P e p p e r o n i P i z z a " ;
t h i s . dough = " T h i n C r u s t Dough " ;
5 t h i s . s a u c e = " M a r i n a r a Sauce " ;
t h i s . t o p p i n g s . add ( " G r a t e d R e g g i a n o Cheese " ) ;
7 t h i s . t o p p i n g s . add ( " S l i c e d P e p p e r o n i " ) ;
t h i s . t o p p i n g s . add ( " G a r l i c " ) ;
9 t h i s . t o p p i n g s . add ( " Onion " ) ;
t h i s . t o p p i n g s . add ( " Mushrooms " ) ;
11 t h i s . t o p p i n g s . add ( " Red P e p p e r " ) ;
}
13
void cut ( ) {
15 System . o u t . p r i n t l n ( " C u t t i n g t h e p i z z a i n t o 8 s l i c e s " ) ;
}
17 }

152 186
A couple of the concrete product classes

1 public c l a s s ChicagoStylePepperoniPizza extends Pizza {


public ChicagoStylePepperoniPizza ( ) {
3 t h i s . name = " C h i c a go S t y l e P e p p e r o n i P i z z a " ;
t h i s . dough = " E x t r a T h i c k C r u s t Dough " ;
5 t h i s . s a u c e = " Plum Tomato Sauce " ;
t h i s . t o p p i n g s . add ( " S hre dde d M o z z a r e l l a Cheese " ) ;
7 t h i s . t o p p i n g s . add ( " B l a c k O l i v e s " ) ;
t h i s . t o p p i n g s . add ( " S p i n a c h " ) ;
9 t h i s . t o p p i n g s . add ( " E g g p l a n t " ) ;
t h i s . t o p p i n g s . add ( " S l i c e d P e p p e r o n i " ) ;
11 }

13 void cut ( ) {
System . o u t . p r i n t l n ( " C u t t i n g t h e p i z z a i n t o s q u a r e s l i c e s " ) ;
15 }
}

153 186
Factory Method Pizza Demonstration

public c l a s s FactoryMethodPizzaTestDrive {
2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
P i z z a S t o r e n y S t o r e = new N Y P i z z a S t o r e ( ) ;
4 P i z z a S t o r e c h i c a g o S t o r e = new C h i c a g o P i z z a S t o r e ( ) ;

6 Pizza pizza = nyStore . orderPizza ( " pepperoni " ) ;


System . o u t . p r i n t l n ( " Ethan o r d e r e d a " + p i z z a . getName ( ) + " \ n " ) ;
8
Pizza pizza = chicagoStore . orderPizza ( " pepperoni " ) ;
10 System . o u t . p r i n t l n ( " J o e l o r d e r e d a " + p i z z a . getName ( ) + " \ n " ) ;
}
12 }

154 186
Definition of Factory Method Pattern

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

The Factory Method Pattern gives us a way to encapsulate the instantiations of concrete
types.
The Pattern gives you an interface with a method for creating objects, also known as the
"factory method".
The subclasses actually implement the factory method and create products.

155 186
Structure of Factory Method Pattern

156 186
Dependency Inversion Principle

Factory Method is one way of following the Dependency Inversion Principle.


▶ "Depend upon abstractions. Do not depend upon concrete classes."

Normally "high-level" classes depend on "low-level" classes.


▶ Instead, they BOTH should depend on an abstract interface.

157 186
Dependency Inversion Principle: Pictorially

158 186
Dependency Inversion Principle: Pictorially

159 186
Dependency Inversion Principle: How To?

To achieve the Dependency Inversion Principle in your own designs, follow these
GUIDELINES.
▶ No variable should hold a reference to a concrete class.
- If you use new, you’ll be holding a reference to a concrete class. Use a factory to get around that!
▶ No class should derive from a concrete class.
- If you derive from a concrete class, you’re depending on a concrete class. Derive from an
abstraction, like an interface or an abstract class.
▶ No method should override an implemented method of its base classes.
- If you override an implemented method, then your base class wasn’t really an abstraction to start
with. Those methods implemented in the base class are meant to be shared by all your subclasses.

These are "guidelines" because if you were to blindly follow these instructions, you would
never produce a system that could be compiled or executed.
▶ Instead use them as instructions to help optimize your design.

And remember, not only should low-level classes depend on abstractions, but high-level
classes should to . . . This is the very embodiment of "code to an interface".
160 186
Moving On

The Factory Method approach to the pizza store is a big success, allowing our company to
create multiple franchises across the country quickly and easily.
▶ But (bad news): we have learned that some of the franchises.
- while following our procedures (the abstract code in PizzaStore forces them to)
- are skimping on ingredients in order to lower costs and increase margins.
▶ Our company’s success has always been dependent on the use of fresh, quality ingredients.
- So, something must be done!

We will alter our design such that a factory is used to supply the ingredients that are
needed during the pizza creation process.
▶ Since different regions use different types of ingredients, we’ll create region-specific subclasses
of the ingredient factory to ensure that the right ingredients are used.
▶ But, even with region-specific requirements, since we are supplying the factories, we’ll make
sure that ingredients that meet our quality standards are used by all franchises.
- They’ll have to come up with some other way to lower costs.

161 186
Ensuring consistency in your ingredients

Now there is only one problem with this plan: the franchises are located in different
regions and what is red sauce in New York is not red sauce in Chicago. So, you have one
set of ingredients that needs to be shipped to New York and a different set that needs to be
shipped to Chicago.

162 186
Building the ingredient factories

Now we’re going to build a factory to create our ingredients; the factory will be responsible
for creating each ingredient in the ingredient family. In other words, the factory will need
to create dough, sauce, cheese, and so on...

Let’s start by defining an interface for the factory that is going to create all our ingredients:

public interface PizzaIngredientFactory {


2 Dough c r e a t e D o u g h ( ) ;
Sauce c r e a t e S a u c e ( ) ;
4 Cheese c r e a t e C h e e s e ( ) ;
Veggie [ ] c r e at e V e g g ie s ( ) ;
6 Pepperoni createPepperoni ( ) ;
Clams c r e a t e C l a m s ( ) ;
8 }

163 186
Second, we Implement a Region-Specific Factory

p u b l i c c l a s s C h i c a g o P i z z a I n g r e d i e n t F a c t o r y implements P i z z a I n g r e d i e n t F a c t o r y {
2 p u b l i c Dough c r e a t e D o u g h ( ) {
r e t u r n new T h i c k C r u s t D o u g h ( ) ;
4 }

6 p u b l i c Sauce c r e a t e S a u c e ( ) {
r e t u r n new PlumTomatoSauce ( ) ;
8 }

10 p u b l i c Cheese c r e a t e C h e e s e ( ) {
r e t u r n new M o z z a r e l l a C h e e s e ( ) ;
12 }

14 public Veggies [] createVeggies ( ) {


V e g g i e s v e g g i e s [ ] = { new B l a c k O l i v e s ( ) , new S p i n a c h ( ) , new E g g p l a n t ( ) } ;
16 return veggies ;
}
18 ...
}

164 186
How (or where) is this factory used

1 public abstract class Pizza {


p r o t e c t e d S t r i n g name ;
3 p r o t e c t e d Dough dough ;
p r o t e c t e d Sauce s a u c e ;
5 protected Veggies veggies [ ] ;
p r o t e c t e d Cheese c h e e s e ;
7 protected Pepperoni pepperoni ;
p r o t e c t e d Clams clam ;
9
public abstract void prepare();
11
v o i d bake ( ) {
13 System . o u t . p r i n t l n ( " Bake f o r 25 m i n u t e s a t 3 5 0 " ) ;
}
15
void cut ( ) {
17 System . o u t . p r i n t l n ( " C u t t i n g t h e p i z z a i n t o d i a g o n a l s l i c e s " ) ;
}

165 186
How (or where) is this factory used

public c l a s s CheesePizza extends Pizza {


2 private PizzaIngredientFactory ingredientFactory ;

4 public CheesePizza ( P i z z a I n g r e d i e n t F a c t o r y ingredientFactory ) {


this . ingredientFactory = ingredientFactory ;
6 }

8 public void prepare ( ) {


System . o u t . p r i n t l n ( " P r e p a r i n g " + name ) ;
10 t h i s . dough = i n g r e d i e n t F a c t o r y . c r e a t e D o u g h ( ) ;
t h i s . sauce = i n g r e d i e n t F a c t o r y . createSauce ( ) ;
12 t h i s . cheese = ingredientFactory . createCheese ( ) ;
}
14 }

We no longer need subclasses like NYCheesePizza and ChicagoCheesePizza because the


ingredient factory now handles regional differences.

166 186
How (or where) is this factory used

public c l a s s ChicagoPizzaStore extends PizzaStore {


2 pulic Pizza createPizza ( String style ) {
Pizza pizza = null ;
4 PizzaIngredientFactory ingredientFactory =
new C h i c a g o P i z z a I n g r e d i e n t F a c t o r y ( ) ;
6
i f ( s t y l e . equals ( " cheese " ) ) {
8 p i z z a = new C h e e s e P i z z a ( i n g r e d i e n t F a c t o r y ) ;
p i z z a . setName ( " C h i c a g o S t y l e Cheese P i z z a " ) ;
10 } else i f ( style . equals ( " veggie " ) ) {
p i z z a = new V e g g i e P i z z a ( i n g r e d i e n t F a c t o r y ) ;
12 p i z z a . setName ( " C h i c a g o S t y l e V e g g i e P i z z a " ) ;
}
14 ...

16 return pizza ;
}
18 }

167 186
Summary: What did we just do?

We created an ingredient factory interface to allow for the creation of a family of


ingredients for a particular pizza.

This abstract factory gives us an interface for creating a family of products (e.g., NY pizzas,
Chicago pizzas).
▶ The factory interface decouples the client code from the actual factory implementations that
produce context-specific sets of products.

Our client code (PizzaStore) can then pick the factory appropriate to its region, plug it in,
and get the correct style of pizza (Factory Method) with the correct set of ingredients
(Abstract Factory).

168 186
Class Diagram of Abstract Factory Solution

169 186
Definition of Abstract Factory

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

We’ve certainly seen that Abstract Factory allows a client to use an abstract interface to
create a set of related products without knowing (or caring) about the concrete products
that are actually produced.
In this way, the client is decoupled from any of the specifics of the concrete products.

170 186
Structure of Abstract Factory

171 186
Factory Pattern
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 patterns 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 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.
172 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

173 186
Iterator Pattern

There are lots of ways to stuff objects into a collection.


Put them into an Array, a Stack, a List, a Hash Map - take your pick. Each has its own
advantages and tradeoffs.
How you can iterate through your objects without ever getting a peek at how you store
your objects.

174 186
Menu Example

p u b l i c c l a s s MenuItem {
2 p r i v a t e S t r i n g name ;
private String description ;
4 p r i v a t e double p r i c e ;

6 p u b l i c MenuItem ( S t r i n g name ,
String description ,
8 double p r i c e ) {
t h i s . name = name ;
10 this . description = description ;
this . price = price ;
12 }

14 p u b l i c S t r i n g getName ( ) {
r e t u r n name ;
16 }

18 ...

175 186
Menu Example

p u b l i c c l a s s PancakeHouseMenu {
2 private List<MenuItem> menuItems;

4 p u b l i c PancakeHouseMenu ( ) {
menuItems = new A r r a y L i s t < MenuItem > ( ) ;
6 addItem ( " K&B ’ s Pancake B r e a k f a s t " ,
" P a n c a k e s w i t h s c r a m b l e d e g g s and t o a s t " ,
8 2.99) ;
addItem ( " R e g u l a r Pancake B r e a k f a s t " ,
10 " P a n c a k e s w i t h f r i e d eggs , s a u s a g e " ,
2.99) ;
12 }

14 p u b l i c v o i d addItem ( S t r i n g name , S t r i n g d e s c r i p t i o n , d o u b l e p r i c e ) {
MenuItem menuItem = new MenuItem ( name , d e s c r i p t i o n , p r i c e ) ;
16 menuItems . add ( menuItem ) ;
}
18 ...

176 186
Menu Example

p u b l i c c l a s s DinerMenu {
2 p r i v a t e s t a t i c f i n a l i n t MAX_ITEMS = 6 ;
p r i v a t e i n t numberOfItems = 0 ;
4 private MenuItem[] menuItems;

6 p u b l i c DinerMenu ( ) {
menuItems = new MenuItem [ MAX_ITEMS ] ;
8 addItem ( " V e g e t a r i a n BLT " ,
" ( F a k i n ’ ) Bacon w i t h l e t t u c e & tomato on whole wheat " , t r u e , 2 . 9 9 ) ;
10 addItem ( " BLT " ,
" Bacon w i t h l e t t u c e & tomato on whole wheat " , f a l s e , 2 . 9 9 ) ;
12
p u b l i c v o i d addItem ( S t r i n g name , S t r i n g d e s c r i p t i o n , d o u b l e p r i c e ) {
14 MenuItem menuItem = new MenuItem ( name , d e s c r i p t i o n , p r i c e ) ;
menuItems [ numberOfItems ] = menuItem ;
16 numberOfItems = numberOfItems + 1 ;
}
18 ...

177 186
Menu Example
Now, to print out the items from the PancakeHouseMenu, we’ll loop through the items on
the breakfastItems ArrayList. And to print out the Diner items, we’ll loop through the
Array.

f o r ( i n t i = 0 ; i < b r e a k f a s t I t e m s . s i z e ( ) ; i ++) {
2 MenuItem menuItem = [Link](i);
System . o u t . p r i n t ( menuItem . getName ( ) + " " ) ;
4 System . o u t . p r i n t l n ( menuItem . g e t P r i c e ( ) + " " ) ;
System . o u t . p r i n t l n ( menuItem . g e t D e s c r i p t i o n ( ) ) ;
6 }

8 f o r ( i n t i = 0 ; i < lunchItems . length ; i ++) {


MenuItem menuItem = lunchItems[i];
10 System . o u t . p r i n t ( menuItem . getName ( ) + " " ) ;
System . o u t . p r i n t l n ( menuItem . g e t P r i c e ( ) + " " ) ;
12 System . o u t . p r i n t l n ( menuItem . g e t D e s c r i p t i o n ( ) ) ;
}

178 186
Menu Example
Now what if we create an object, let’s call it an Iterator, that encapsulates the way we
iterate through a collection of objects?

1 public interface Iterator {


boolean hasNext ( ) ;
3 MenuItem n e x t ( ) ;
}
5

7 I t e r a t o r i t e r a t o r = breakfastMenu . c r e a t e I t e r a t o r ( ) ;
while ( i t e r a t o r . hasNext ( ) ) {
9 MenuItem menuItem = i t e r a t o r . n e x t ( ) ;
}
11
I t e r a t o r i t e r a t o r = lunchMenu . c r e a t e I t e r a t o r ( ) ;
13 while ( i t e r a t o r . hasNext ( ) ) {
MenuItem menuItem = i t e r a t o r . n e x t ( ) ;
15 }

179 186
Menu Example

1 p u b l i c c l a s s DinerMenuIterator implements I t e r a t o r {
p r i v a t e MenuItem[] items;
3 private int position = 0;

5 p u b l i c D i n e r M e n u I t e r a t o r ( MenuItem [ ] i t e m s ) {
t h i s . items = items ;
7 }

9 p u b l i c MenuItem next() {
MenuItem menuItem = i t e m s [ p o s i t i o n ] ;
11 position ++;
r e t u r n menuItem ;
13 }

15 p u b l i c boolean hasNext ( ) {
i f ( p o s i t i o n >= i t e m s . l e n g t h | | i t e m s [ p o s i t i o n ] == n u l l ) {
17 return false ;
}
19
return true ;
21 }
}

180 186
Working the DinerMenu with Iterator

p u b l i c c l a s s DinerMenu {
2 p r i v a t e s t a t i c f i n a l i n t MAX_ITEMS = 6 ;
p r i v a t e i n t numberOfItems = 0 ;
4 p r i v a t e MenuItem [ ] menuItems ;

6 / / c o n s t r u c t o r here

8 / / addItem h e r e

10 / ∗ We a r e n o t g o i n g t o need t h e getMenuItems ( ) method anymore ; i n f a c t ,


we do n o t want i t b e c a u s e i t e x p o s e s o u r i n t e r n a l i m p l e m e n t a t i o n ! ∗ /
12 public MenuItem[] getMenuItems() {
return menuItems;
14 }

16 public Iterator createIterator() {


return new DinerMenuIterator(menuItems);
18 }
}

181 186
Working the DinerMenu with Iterator

1 p u b l i c c l a s s MenuTestDrive {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 I t e r a t o r p a n c a k e I t e r a t o r = pancakeHouseMenu . c r e a t e I t e r a t o r ( ) ;
printMenu ( p a n c a k e I t e r a t o r ) ;
5
I t e r a t o r d i n e r I t e r a t o r = dinerMenu . c r e a t e I t e r a t o r ( ) ;
7 printMenu ( d i n e r I t e r a t o r ) ;
}
9
p r i v a t e s t a t i c v o i d printMenu ( I t e r a t o r i t e r a t o r ) {
11 while ( i t e r a t o r . hasNext ( ) ) {
MenuItem menuItem = i t e r a t o r . n e x t ( ) ;
13 System . o u t . p r i n t ( menuItem . getName ( ) + " , " ) ;
System . o u t . p r i n t ( menuItem . g e t P r i c e ( ) + " −− " ) ;
15 System . o u t . p r i n t l n ( menuItem . g e t D e s c r i p t i o n ( ) ) ;
}
17 }
}

182 186
Definition of Abstract Factory

Iterator Pattern
The Iterator Pattern provides a way to access the elements of an aggregate object
sequentially without exposing its underlying representation.

The Iterator Pattern allows traversal of the elements of an aggregate without exposing the
underlying implementation
It also 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.

183 186
Structure of Iterator Pattern

184 186
Presentation Outline

1 Motivations

2 Introduction to Design Patterns

3 Design Patterns
Strategy Pattern
Singleton Pattern
Adapter Pattern
Facade Pattern
Observer Pattern
Template Method Pattern
Decorator Pattern
Factory Pattern
Iterator Pattern

4 References

185 186
References

Allen B. Downey, Chris Mayfield, Think Java, (2016).


Graham Mitchell, Learn Java the Hard Way, 2nd Edition, (2016).
Cay S. Horstmann, Big Java - Early Objects, 7e-Wiley, (2019).
James Gosling, Bill Joy, Guy Steele, Gilad Bracha, Alex Buckley, The Java Language Specification -
Java SE 8 Edition, (2015).
Martin Fowler, UML Distilled - A Brief Guide To The Standard Object Modeling Language,
(2004).
Richard Warburton, Object-Oriented vs. Functional Programming - Bridging the Divide
Between Opposing Paradigms, (2016).
Naftalin, Maurice Wadler, Philip Java Generics and Collections, O’Reilly Media, (2009).
Eric Freeman, Elisabeth Robson Head First Design Patterns - Building Extensible and
Maintainable Object, Oriented Software-O’Reilly Media, (2020).
Alexander Shvets Dive Into Design Patterns, (2019).

186 / 186
Thank You!

You might also like