0% found this document useful (0 votes)
49 views28 pages

The Strategy Pattern

The Strategy Pattern allows behaviors to be changed at runtime by encapsulating varying behavior into interchangeable strategy objects. For a duck simulation game, the developer originally added a fly() method to the base Duck class, unintentionally enabling all ducks to fly. To address this, the developer proposes using interfaces to define varying behaviors like flying and quacking, with concrete strategy classes implementing each behavior. This avoids duplicating code across subclasses and makes the behaviors independent of the duck classes and changeable without affecting the classes.

Uploaded by

Thanh Điền
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views28 pages

The Strategy Pattern

The Strategy Pattern allows behaviors to be changed at runtime by encapsulating varying behavior into interchangeable strategy objects. For a duck simulation game, the developer originally added a fly() method to the base Duck class, unintentionally enabling all ducks to fly. To address this, the developer proposes using interfaces to define varying behaviors like flying and quacking, with concrete strategy classes implementing each behavior. This avoids duplicating code across subclasses and makes the behaviors independent of the duck classes and changeable without affecting the classes.

Uploaded by

Thanh Điền
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 28

The Strategy Pattern

1
The Specifications
• Joe works at a company that
produces a simulation game
called SimUDuck.
He is an OO Programmer
and his duty is to implement
the necessary functionality
for the game

• The game should have the following specifications:


– A variety of different ducks should be integrated into the
game
– The ducks should swim
– The ducks should quack

2
A First Design for the
Duck Simulator Game
Duck
All ducks quack() and swim(). The
superclass takes care of the implementation
quack()
swim()
display() The display() method is abstract since
//other duck like methods all the duck subtypes look different

Each duck subtype is responsible for


MallardDuck RedHeadDuck implementing its own display()
behavior for how it looks on the screen
display() display()
Lots of other types of ducks
inherit from the Duck type

3
But now we need the ducks to fly…
Joe, at the shareholders meeting we
decided that we need to crush the
competition. From now on our ducks
need to fly.

Duck

quack()
swim()
display()
fly() All subclasses inherit fly()

MallardDuck RedHeadDuck

display() display()
4
But something went horribly wrong..
• At a demo the program failed to impress anyone –
There were rubber ducks flying across the screen!
What happened? Duck
A localized update to the code
caused a non-local side effect quack()
(flying rubber ducks) swim() By putting fly() in the
display() superclass, Joe gave flying
fly() ability to all ducks including
those that shouldn’t

MallardDuck RedHeadDuck RubberDuck

display() display() quack()


display()
5
Inheritance at Work
public class Duck {
Duck
...
public void fly() {
+quack() // fly implementation
+swim()
+display() }
+fly() public void quack() {
System.out.println("quack, quack");
}
}
RubberDuck
We can override the fly() method in the
MallardDuck RedHeadDuck
rubber duck in a similar way that we override
+quack() the quack() method
+display() +display()
+fly()
+display()
public class RubberDuck
extends Duck {
quack squick
...
quack
public void fly() { }
public void quack() {
System.out.println(
"squick, squick");
}
} 6
Yet Another Duck is Added
to the Application
Duck What would happen if we added a
DecoyDuck to the class hierarchy?
+quack()
+swim() It doesn’t quack() or fly().
+display()
+fly()
public class DecoyDuck
extends Duck {
...

public void fly() {


MallardDuck RedHeadDuck RubberDuck DecoyDuck
// do nothing
}
+display() +display() +quack() +quack()
+fly() +fly() public void quack() {
+display() +display()
// do nothing
}
}

7
How about an interface?
• Need a cleaner way to make some ducks fly or quack.
– Could take the fly() out of the superclass and make an
Flyable interface with a fly() method. Each duck that is
supposed to fly will implement that interface
– and maybe a Quackable interface as well.
<<Interface>> <<Interface>> Duck
Flyable Quackable
+ swim()
+ fly() + quack() + display()
// other duck like methods
What do you
think about
this design?

MallardDuck RedHeadDuck RubberDuck DecoyDuck

+ fly() + fly() + quack() + display()


+ quack() + quack() + display()
+ display() + display()
8
What do you think?
• Dumb!!!!

• “Duplicate code” all over the place.


– Interface not reuse code
– A small change to the flying behavior will require
changing all 48 of the Duck subclasses!

9
Embracing Change
• In SOFTWARE projects you can count on one thing
that is constant:

CHANGE
• Solution
– Deal with it.
• Make CHANGE part of your design.
• Identify what vary and separate from the rest.

Let’s shoot some ducks!

10
Change is a taste of life

11
Design Principle

Encapsulate
what varies

12
The Constitution of Software Architects
• Encapsulate what varies.
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????

13
Embracing Change in Ducks
• fly() and quack() are the parts that vary
• We create a new set of classes to represent each behavior
<<Interface>> <<Interface>>
FlyBehavior QuackBehavior

+ fly() + quack()

FlyWithWings FlyNoWay Quack Squick MuteQuack

+ fly() + fly() + quack() + quack() + quack()

print("I'm flying!") print("Quack") print("...")

print("I can't fly.") print("Squeak")

14
Design Principle

Program to an interface not


to an implementation

15
The Constitution of Software Architects
• Encapsulate what varies.
• Program through an interface
not to an implementation
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????

16
Design Principle Example

Animal
Program through an implementation
+ makeSound() Dog dog = createDog();
dog.bark();

Dog Cat Program through an interface


+ makeSound() { + makeSound() { Animal dog = createDog();
bark(); meow(); dog.makeSound();
} }
+ bark() + moew()

17
Integrating the Duck Behavior
Instance variables
The behavior variables Duck hold a reference to
are declared as the # flyBehavior : FlyBehavior a specific behavior
behavior interface type. # quackBehavior : QuackBehavior at runtime.
+ performQuack() quackBehavior.quack();
These replace the + performFly()
fly() and quack() + swim() flyBehavior.fly();
+ display()
methods.

MallardDuck RedHeadDuck RubberDuck DecoyDuck

+ display() + display() + display() + display()

class MallardDuck extends Duck class DecoyDuck extends Duck


public MallardDuck(){ public DecoyDuck(){
flyBehavior = new FlyWithWings(); flyBehavior = new FlyNoWay();
quackBehavior = new Quack(); quackBehavior = new MuteQuack();
} }
} } 18
Design Principle Ahead
Duck Each Duck HAS A FlyingBehavior and
# flyBehavior : FlyBehavior a QuackBehavior to which it delegates
# quackBehavior : QuackBehavior flying and quacking behaviors

+ performQuack()
+ performFly() Composition
+ swim()
+ display()
Instead of inheriting behavior, the duck
get their behavior by being composed
with the right behavior object

19
Design Principle

Favor Composition over


Inheritance

20
The Constitution of Software Architects
• Encapsulate what varies.
• Program through an interface
not to an implementation
• Favor Composition over
Inheritance
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
• ?????????
21
Putting it together…
public interface QuackBehavior {
void quack();
}
public interface FlyBehavior {
void fly();
} public abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;

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

public performFly() {
flyBehavior.fly();
}
}
22
Putting it together…
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public class Quack implements QuackBehavior {
}
public void quack() {
System.out.println("Quack");
}
public class FlyWithWings implements FlyBehavior {
}
public void fly() {
System.out.println("I'm flying!!");
}
}

public class MiniDuckSimulator {


public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack(); I'm a real Mallard duck
mallard.performFly(); Quack
} I'm flying!!
}
23
Setting Behavior Dynamically!
Duck public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
- flyBehavior : FlyBehavior
}
- quackBehavior : QuackBehavior
public void setQuackBehavior(QuackBehavior qb) {
+ performFly() quackBehavior = qb;
+ performQuack() }
+ swim()
+ display() // Test it out in main
+ setFlyBehavior(fb : FlyBehavior)
+ setQuackBehavior(qb : QuackBehavior) Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(
// Create a new type of Duck new FlyRocketPowered());
public class ModelDuck extends Duck { model.performFly();
public ModelDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new Quack()); I'm a model duck
}
public void display() { I can’t fly
System.out.println("I'm a model duck"); I'm flying with a rocket
}
} // Make a new FlyBehavior type
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
} 24
The Big Picture <<Interface>>
FlyBehavior
Duck
# flyBehavior : FlyBehavior + fly()
# quackBehavior : QuackBehavior

+ performFly()
+ performQuack()
+ swim() FlyWithWings FlyNoWay FlyRocketPower
+ display() + fly() + fly() + fly()
+ setFlyBehavior(f : FlyBehavior)
+ setQuackBehavior(q : QuackBehavior)
<<Interface>>
QuackBehavior

MallardDuck RedHeadDuck RubberDuck DecoyDuck

+ display() + display() + display() + display()


Quack Squick MuteQuack

+ quack() + quack() + quack()

25
Behavior Reuse <<Interface>>
FlyBehavior
Duck
- flyBehavior : FlyBehavior + fly()
- quackBehavior : QuackBehavior

+ performFly()
+ performQuack()
+ swim() FlyWithWings FlyNoWay
+ display()
+ setFlyBehavior(f : FlyBehavior) + fly() + fly()
+ setQuackBehavior(q : QuackBehavior)
<<Interface>>
QuackBehavior

MallardDuck RedHeadDuck RubberDuck DecoyDuck


+ display() + display() + display() + display()
Quack Squick MuteQuack

+ quack() + quack() + quack()

Plane
- flyBehavior : FlyBehavior
+ performFly()

AirForceOne Airbus Boeing Apache

26
The Strategy Design Pattern
The Strategy Design Pattern defines a family of algorithms,
encapsulates each one, and makes them interchangeable.
Strategy lets the algorithms vary independently from the clients that use
it.
Context manages the data structures
that a concrete strategy operates on.
Defines the generic interface
Context
- strategy : Strategy <<Interface>>
Strategy
+ Context(s : Strategy)
+ setStrategy(s : Strategy) + runAlgorithm()
+ runAlgorithm()

strategy.runAlgorithm(); ConcreteStrategyA ConcreteStrategyB ConcreteStrategyC

+ runAlgorithm() + runAlgorithm() + runAlgorithm()

ConcreteStrategy classes provide the implementations of the different strategies.


These operate on the data structures in the the Context, and can be set dynamically.
27
Summary
• Strategy pattern allows selection of one of several
algorithms dynamically.
• Algorithms may be related via an inheritance
hierarchy or unrelated [must implement the same
interface]
• Strategies don’t hide everything -- client code is
typically aware that there are a number of strategies
and has some criteria to choose among them --
shifts the algorithm decision to the client.

28

You might also like