[go: up one dir, main page]

0% found this document useful (0 votes)
1 views30 pages

01 - Strategy Pattern

The document discusses the Strategy Pattern in object-oriented design, using the example of a duck simulation game where different duck behaviors (flying and quacking) are encapsulated into separate classes rather than being hardcoded into a Duck superclass. This approach allows for greater flexibility and easier maintenance, as behaviors can be changed at runtime without affecting other parts of the system. The document emphasizes the importance of using design patterns to create reusable, extensible, and maintainable software solutions.

Uploaded by

gamedark01
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)
1 views30 pages

01 - Strategy Pattern

The document discusses the Strategy Pattern in object-oriented design, using the example of a duck simulation game where different duck behaviors (flying and quacking) are encapsulated into separate classes rather than being hardcoded into a Duck superclass. This approach allows for greater flexibility and easier maintenance, as behaviors can be changed at runtime without affecting other parts of the system. The document emphasizes the importance of using design patterns to create reusable, extensible, and maintainable software solutions.

Uploaded by

gamedark01
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
You are on page 1/ 30

CSE351 DESIGN PATTERNS

01. STRATEGY PATTERN

Someone has already


solved your problems.
It started with a simple SimUDuck app
▪ You are the designer of a highly successful duck pond simulation game, SimUDuck.
▪ Initial designers of the simulator used standard OO techniques and created one Duck
superclass from which all other duck types inherit.

Company executives think it’s


time for a big innovation to
show at the upcoming fair.
2
But now we need the ducks to FLY
The executives decided that flying ducks is just what the
simulator needs to blow away other duck sim competitors.
And your manager told it’ll be no problem.
▪ After all you are an OO programmer, how hard it can be?

3
But something went horribly wrong…
What happened?
- Failed to notice that not all subclasses of Duck fly
- Behavior is added to Duck superclass which is not appropriate for
some Duck subclasses
- A localized update to the code caused a non-local side effect
(flying rubber ducks)!

4
Let’s think about inheritance…
Sharpen your pencil
Which of the following are disadvantages of
using inheritance to provide Duck behavior?
(choose all that apply)
A. Code is duplicated across subclasses.
B. Runtime behavior changes are difficult
C. We can’t make ducks dance.
D. Hard to gain knowledge of all duck
behaviors.
E. Ducks can’t fly and quack at the same
time.
F. Changes can unintentionally affect other
ducks.
5
How about an interface?
▪ Inheritance probably wasn’t the answer
▪ Because execs now want to update the product every six
months (in ways that haven’t decided yet).
▪ Will need to override fly() and quack() for every new
Duck subclass
▪ Need a cleaner way to have only some (but not all) of the duck
types fly or quack

What do YOU
think of this
design?
6
What would you do instead?
▪ Not all subclasses should have flying or
quacking behavior, so inheritance isn’t the
right answer
▪ Having subclasses implement Flyable
and/or Quackable partly solves the
problem, but it destroys code reuse
▪ A different maintenance nightmare!
▪ Also there might be more than one kind of flying
behavior among ducks that do fly
▪ Let’s figure out a solution the old-fashioned-
way
▪ by applying good OO software design principles

7
The one constant in software development
Okay, what’s the one thing you can always count on in software development?
▪ No matter where you work, what you’re building, or what language you programming in, what’s
one true constant that will be always with you?

▪ No matter how well you design an application, over time an application must grow and change
or it will die.

8
Zeroing in on the problem…
• Using inheritance hasn’t worked out well
• Duck behavior keeps changing across subclasses
• Flyable and Quackable interface sounded promising at first
• Except Java interfaces have no implementation code, no code reuse!
• Whenever you need a modification, you need to track down in all
different subclasses

• As simple as it is,
• It forms the basis for almost every design pattern
• All patterns provide a way to let some part of a system vary
independently of all other parts
9
Separating what changes from what stays the same
▪ fly() and quack() are
the parts of the Duck
class that vary across
ducks.
▪ To separate these
behaviors, let’s pull both
methods out of the Duck
class and create new set
of classes to represent
each behavior

10
Designing the Duck behaviors
• We’d like to keep things flexible.
• Assign behaviors to instances of Duck
• e.g., instantiate a new MallardDuck instance and initialize with a specific type
of flying behavior
YOUR TURN
Now, explain how we did achieve
programming to an interface rather
an implementation in this example?

• Use an interface to represent each behavior, FlyBehavior and QuackBehavior


• Each implementation of a behavior will implement one of those interfaces
• Make sets of classes whose entire reason for living is to represent a behavior
(e.g., squeaking), and it is the Behavior class rather than the Duck class, that
will implement the behavior interface

11
<Program to an interface> really means <Program to a supertype>
▪ The word interface is overloaded here.
▪ There’s the concept of interface, but there’s also java construct interface
▪ You can program to an interface, without using Java interface
▪ using an abstract class or interface – supertype (exploit polymorphism)
Programming to an implementation would be:

But programming to an interface/supertype would be:

Even better, rather than hard-coding the instantiation of the subtype


(like new Dog()), assign concrete implementation object at runtime:

12
Implementing the Duck Behaviors
With this design, other types of
objects can reuse our fly and quack
behaviors because they are no longer
hidden away in our Duck class!

And we can add new behaviors


without modifying any of our
existing behavior classes or touching
any of Duck classes that use flying
behaviors

13
there are no
Dumb Questions
Q: Do I always have to implement my Q: It feels weird to have a class that’s just a
application first, see where things are changing, behavior. Aren’t classes supposed to represent
and then go back and separate & encapsulate
them? things? Aren’t classes supposed to have both
state AND behavior?
A: Not always; often when you are designing an
application you anticipate that might vary. A: In an OO system, yes, classes represent things
Principles and patterns can be applied at any that generally have both state (instance variables)
stage of development cycle. and Methods. Here, the thing happens to be a
behavior. But even a behavior can still have state
Q: Should we make Duck an interface too? and methods; a flying behavior might have instance
variables representing attributes (beats per
A: Not in this case. We’ve got everything hooked
together, we do benefit by having Duck be a minute, max altitude and speed, etc.) for flying
concrete class and having specific ducks, like behavior.
MallardDuck, inherit common properties and
methods.
14
Sharpen your pencil

1. Using our new design, what would you do if you needed to add
rocket-powered flying to the SimUDuck app?
Create a FlyRocketPowered class
that implements the FlyBehavior
interface.
2. Can you think of a class that might want to use the Quack
behavior that isn’t a duck? One example, a duck call (a device that makes
duck sounds).
Another example is a charlatan or a
mountebank person [check out here].
15
Integrating the Duck Behavior
The key is that a Duck will now delegate its flying and quacking behavior, instead of using
quacking and flying methods defined in the Duck class (or subclass).
1. Add two instance variables to the 2. Also replace fly() and quack() in the Duck class
Duck class called flyBehavior with performFly() and performQuack().
and quackBehavior declared as
interface type. Each duck object will
set these variables polymorphically
to reference specific type it would
like at runtime (FlyWithWings,
Squeak, etc.).

3. Now implement performQuack()

16
More integration…
4. How the flyBehavior and quackBehavior instance variables are set.
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}

public void display() {


System.out.println(“I’m a real Mallard duck”);
}
}
▪ So MallardDuck’s quack is a real live duck quack, not a squeak and not a mute quack.
▪ When a MallardDuck is instantiated, its constructor initializes the MallardDuck’s inherited
"quackBehavior" instance variable to a new instance of type Quack (a QuackBehavior concrete
implementation class).
▪ And the same with the flying behavior. 17
▪ Good catch, yes we do, just for
now.
▪ We’ll fix it later with other Design
Patterns.
▪ Still, we are setting the behaviors
to concrete classes that we could
easily change at runtime (through
magic of polymorphism)
Take a moment and think about how you
? would implement a duck so that its behavior
could change at runtime.
18
Testing the Duck code
Duck.java - also consider MallardDuck.java
public abstract class Duck { FlyBehavior.java FlyWithWings.java FlyNoWay.java
FlyBehavior flyBehavior;
QuackBehavior quackBehavior; public interface FlyBehavior {
public Duck() { public void fly();
} }
public abstract void display();
public class FlyWithWings implements FlyBehavior {
public void performFly() { public void fly() {
flyBehavior.fly(); System.out.println(“I’m flying!!”);
} }
}
public void performQuack() {
quackBehavior.quack(); public class FlyNoWay implements FlyBehavior {
}
public void fly() {
public void swim() { System.out.println(“I can’t fly”);
System.out.println(“All ducks float, even decoys!”); }
} }
}

19
Testing the Duck code continued…
Quack Behavior interface QuackBehavior.java, Quack.java, MuteQuack.java, and Squeak.java
public interface QuackBehavior {
public void quack(); MiniDuckSimulator.java
} public class MiniDuckSimulator {
public static void main(String[] args) {
public class Quack implements QuackBehavior { Duck mallard = new MallardDuck();
public void quack() { mallard.performQuack();
System.out.println(“Quack”); mallard.performFly();
} }
} }

public class MuteQuack implements QuackBehavior {


public void quack() {
System.out.println(“<< Silence >>”);
} Run the code
}

public class Squeak implements QuackBehavior {


public void quack() {
System.out.println(“Squeak”);
}
}
20
Setting behavior dynamically
1. Add two new methods to the Duck Class
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}

We can call these methods anytime we want


to change the behavior of a duck on the fly

2. Make a new Duck type (ModelDuck.java)


public class ModelDuck extends Duck {
public ModelDuck() { 3. Make a new FlyBehavior type
flyBehavior = new FlyNoWay(); (FlyRocketPowered.java)
quackBehavior = new Quack();
} public class FlyRocketPowered implements FlyBehavior {
public void display() { public void fly() {
System.out.println(“I’m a model duck”); System.out.println(“I’m flying with a rocket!”);
} }
}
} 21
4. Change the test class, add ModelDuck and make ModelDuck rocket-enabled, and run it!

22
The Big Picture on encapsulated behaviors

Pay careful attention to


the relationships.

Now assign right


relations to the
appropriate arrows
(IS-A, HAS-A and
IMPLEMENTS)

23
HAS-A can be better than IS-A
▪ The HAS-A relationship is interesting: each duck has a FlyBehavior and a QuackBehavior to
which it delegates flying and quacking.
▪ When you put two classes together you’re using composition.
▪ Instead of inheriting their behavior, the ducks get their behavior by composed with the right
behavior object

▪ Creating systems using composition gives a lot flexibility.


▪ Not only encapsulating a family of algorithms into their own set of classes, but also letting change
behavior at runtime
▪ Composition is used in many design patterns and you’ll see a lot more about its advantages and
disadvantages
24
Speaking of Design Patterns
▪ You just applied a pattern – STRATEGY pattern.
▪ You used Strategy Pattern to rework the SimUDuck
app. Thanks to this pattern, the simulator is ready for
any changes those execs might cook up on their next
business trip.
▪ Here is the formal definition.

25
Overheards
Design patterns give
you a shared
vocabulary which
elevates your thinking
about architecture by
letting you think at
the pattern level, not
the nitty gritty object
level.
• What is the difference between these two
orders? Not a thing!
• What’s Flo got that Alice doesn’t is a
shared vocabulary.
• Easier to communicate with the cook and
gives cook less to remember, because he’s
got all dinner patterns.
26
The power of a shared vocabulary
When you communicate using patterns you are doing
more than just sharing LINGO.
✓ Shared pattern vocabularies are POWERFUL
✓Not just pattern name but a whole set of qualities,
characteristics and constraints
✓Patterns allow you to say more with less
✓Talking at the pattern level allows you to stay «in the design»
longer
✓Discuss at the design level not implementation
✓Shared vocabularies can turbo charge your team
✓Move more quickly with less misunderstanding
✓Shared vocabularies encourage junior developers to get up to
speed
✓Seniors shall motivate juniors
27
How do I use Design Patterns?
▪ Think of off-the-shelf libraries and frameworks. THEY DON'T HELP
▪ Java APIs and all the functionality they give STRUCTURING YOUR CODE
you: network, GUI, IO, etc.

Design patterns
don’t go directly
into your code,
they first go into
your BRAIN.

28
there are no
Dumb Questions
Q: If design patterns are so great, why can’t Q: Aren’t libraries and frameworks also design
someone build a library of them so I don’t have to? patterns?
A: Design patterns are higher level than libraries. A: Frameworks and libraries are not design patterns;
Design patterns tell us how to structure classes they provide specific implementations that we link
and objects to solve certain problems and it is our into our code. Sometimes, however, libraries and
job to adapt those designs to fit our particular frameworks make use of design patterns in their
application. implementations. That’s great, because once you
understand design patterns, you’ll more quickly
understand APIs that are structured around design
Q: So, there are no libraries of design patterns? patterns.
A: No, but you will learn later about
pattern catalogs with lists of patterns that
you can apply to your applications.

29
Tools for your Design Toolbox
Let’s look at the tools you’ve put in your OO toolbox.
Bullet Points
▪ Knowing the OO basics does not make you a good
OO designer
▪ Good OO designs are reusable, extensible and
maintainable
▪ Patterns are proven OO experience
▪ Patterns don’t give you code, they give you general
solutions to design problems.
▪ Patterns aren’t invented, they are discovered
▪ Most patterns and principles
▪ address issues of change in software
▪ allow some part of a system vary independently

30

You might also like