Chapter 23 Strategy

97
Chapter 23 Strategy Summary prepared by Kirk Scott 1

description

Chapter 23 Strategy. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 23 Strategy. Summary prepared by Kirk Scott. The Introduction Before the Introduction. In general, a single strategy might be thought of as an algorithm or an operation - PowerPoint PPT Presentation

Transcript of Chapter 23 Strategy

Page 1: Chapter 23 Strategy

1

Chapter 23Strategy

Summary prepared by Kirk Scott

Page 2: Chapter 23 Strategy

2

Page 3: Chapter 23 Strategy

3

Page 4: Chapter 23 Strategy

4

Design Patterns in JavaChapter 23

Strategy

Summary prepared by Kirk Scott

Page 5: Chapter 23 Strategy

5

The Introduction Before the Introduction

• In general, a single strategy might be thought of as an algorithm or an operation

• In the context of the Strategy design pattern, the idea is that there are multiple approaches to doing something, depending on certain conditions or context

• The Strategy design pattern, then, depends on picking the approach or picking the strategy

Page 6: Chapter 23 Strategy

6

• When there is more than one way to go about doing something, complexity can result

• There are the implementations of the different strategies

• There is also the code for choosing which strategy to use

Page 7: Chapter 23 Strategy

7

• The purpose of the Strategy design pattern is to separate the implementations of different strategies from each other

• It also separates the code for picking the strategy from the strategy implementations

Page 8: Chapter 23 Strategy

8

• The pattern defines a single interface for all strategies

• The separate strategies are implemented with a method of the same name in each of the classes implementing the interface

Page 9: Chapter 23 Strategy

9

• Which strategy is used will depend on what kind of object the method implementing the strategy is called on

• The intent of the pattern is realized through an interface and depends on polymorphism and dynamic binding

Page 10: Chapter 23 Strategy

10

Book Definition of Pattern

• Book definition:• The intent of Strategy is to encapsulate

alternative approaches, or strategies, in separate classes that each implement a common operation.

Page 11: Chapter 23 Strategy

11

Modeling Strategies

• Like with the previous chapters, and others, the book illustrates the Strategy design pattern in the following way:

• It develops an example with multiple strategies that doesn’t use the Strategy design pattern

• It then refactors the example using the Strategy design pattern

Page 12: Chapter 23 Strategy

12

Example Scenario

• When a potential customer calls in, interested in buying fireworks, there is software which will make a recommendation or suggestion

• There are several different ways a recommendation can be made

Page 13: Chapter 23 Strategy

13

• Ways of recommending a purchase:• Recommend a particular firework that is being

promoted• Use a piece of software, Rel8• Use another piece of software, LikeMyStuff • Use a default recommendation option

Page 14: Chapter 23 Strategy

14

Promoted Firework

• There is nothing special about this option• If the company is promoting a firework,

recommend it

Page 15: Chapter 23 Strategy

15

Rel8

• Rel8 relies on a customer’s already being registered

• During registration the customer specifies preferences in entertainment and fireworks

• Rel8 makes a suggestion based on the similarity of the customer to other customers (presumably suggesting something that similar customers have tended to buy)

• If the customer isn’t registered, Rel8 can’t be used

Page 16: Chapter 23 Strategy

16

LikeMyStuff

• LikeMyStuff doesn’t rely on pre-registration, but it does rely on customer information

• The idea is that it will make a recommendation based on a profile of recent purchases by the customer

• If not enough data can be obtained to form the profile, then LikeMyStuff can’t be used

Page 17: Chapter 23 Strategy

17

The Default Option

• This is the default:• If none of the previous options applies, then a

firework is suggested at random

Page 18: Chapter 23 Strategy

18

UML for the Scenario

• The UML diagram on the following overhead shows the classes involved in the design as described so far

• Appendix D on UML clarifies the notation:• “Use a dashed arrow between classes to show a

dependency that does not use an object reference. For example, the Customer class relies on a static method from the LikeMyStuff recommendation engine.”

Page 19: Chapter 23 Strategy

19

Page 20: Chapter 23 Strategy

20

The getRecommended() Method

• Viewing the scenario from the top down, what you have is this:

• The Customer class has a getRecommended() method in it

• This method consists of if/else code which chooses one of the strategies, whether to do a promotion, or to use Rel8, LikeMyStuff, or the default

Page 21: Chapter 23 Strategy

21

Doing a Promotion

• If there is a promotion underway, the first part of the logic of getRecommended() deals with that case

• The logic for doing a promotion consists of looking up the contents of a file named strategy.dat in a directory named config

• If there is such a file, its contents should look something like this: promote=JSquirrel

Page 22: Chapter 23 Strategy

22

• The basic idea is that if the data file is not empty, the firework it contains is returned

• If its contents come up null you go on to the next option

• Also, if the file read doesn’t work, you don’t do anything in the catch block, you just continue on to the other options

Page 23: Chapter 23 Strategy

23

Using Rel8

• The Rel8 class has a method advise()• getRecommended() wraps a call to advise() if the

Rel8 strategy is selected• The call looks like this:• if(isRegistered())• return (Firework) Rel8.advise(this);

• “this” is the customer, and Rel8 relies entirely on the information contained in the registered customer object

Page 24: Chapter 23 Strategy

24

Using LikeMyStuff

• The LikeMyStuff class has a suggest() method• getRecommended() wraps a call to suggest() if

the LikeMyStuff strategy is selected• The call looks like this:• if(spendingSince(cal.getTime()) > 1000)• return (Firework) LikeMyStuff.suggest(this);

Page 25: Chapter 23 Strategy

25

• spendingSince() is called on the implicit parameter, customer

• cal in the parameter refers to an instance of Calendar

• getTime() specifies a recent period of time• “this” is the customer, which is sent as a

parameter to suggest()

Page 26: Chapter 23 Strategy

26

• suggest() relies on a database of recent purchases by that customer

• The idea is that if the customer has recently spent $1,000, those purchases provide the basis for a recommendation

Page 27: Chapter 23 Strategy

27

Doing the Default

• The Firework class has a getRandom() method, so if all else fails, getRecommended() wraps a call to that method

Page 28: Chapter 23 Strategy

28

The Code for getRecommended() in the Customer Class

• The code for getRecommended() is shown on the following overheads

• It is a collection of if statements.• It is unfortunate that it is not organized as a

sequence of if/else if’s.

Page 29: Chapter 23 Strategy

29

The Code for getRecommended()• public Firework getRecommended()• {• // if promoting a particular firework, return it• try• {• Properties p = new Properties();•

p.load(ClassLoader.getSystemResourceAsStream(“config/strategy.dat”));• String promotedName = p.getProperty(“promote”);• if(promotedName != null)• {• Firework f = Firework.lookup(promotedName);• if(f != null)• return f;• }

Page 30: Chapter 23 Strategy

30

• catch(Exception ignored)• {• // If resource is missing or it failed to load,• // fall through to the next approach.• }• // if registered, compare to other customers• if(isRegistered())• {• return (Firework) Rel8.advise(this);• }

Page 31: Chapter 23 Strategy

31

• // check spending over the last year• Calendar cal = Calendar.getInstance();• cal.add(Calendar.YEAR, -1);• if(spendingSince(cal.getTime()) > 1000)• return (Firework) LikeMyStuff.suggest(this);

• // oh well!• return Firework.getRandom();• }

Page 32: Chapter 23 Strategy

32

What’s Wrong with the Initial Design

• The book identifies two basic problems with the getRecommended() method as given:

• It’s too long• It combines both selecting a strategy and

executing it

Page 33: Chapter 23 Strategy

33

• This is actually one of the high points of the book

• It explains that you know that the method is too long because you need to put comments in it

• “Short methods are easy to understand, seldom need explanation…”

Page 34: Chapter 23 Strategy

34

Comments Are Bad…

• Finally, what every student always knew: Comments are bad…

• More accurately, you might facetiously say that code which requires comments is bad.

• The book doesn’t say that putting a comment at the beginning for the whole method is bad.

• A useful observation might be that a method should be short and sweet enough that it doesn’t need internal commenting.

Page 35: Chapter 23 Strategy

35

Refactoring to the Strategy Pattern

• Applying the Strategy design pattern involves three things:

• 1. Creating an interface that defines the strategic operation

• 2. Writing classes that implement the interface and embody each of the different strategies

• 3. Refactoring the code to select and use an instance of the right strategy class

Page 36: Chapter 23 Strategy

36

The Interface

• 1. The interface for this example will be named Advisor

• The interface requires the implementation of a recommend() method

• The recommend() method will take a customer as a parameter

• It will return a firework• A UML diagram of the interface is given on the

next overhead

Page 37: Chapter 23 Strategy

37

Page 38: Chapter 23 Strategy

38

The Implementing Classes

• 2. The next step is to write the classes that implement the interface and embody each of the different strategies

• These classes will have to implement the recommend() method

Page 39: Chapter 23 Strategy

39

• The book does the refactoring in part with challenges

• As usual, it’s easiest to just look at the solutions• The UML diagram on the following overhead

shows:– A new Customer class making use of an Advisor

interface– 4 classes which implement the interface and

embody the 4 strategies

Page 40: Chapter 23 Strategy

40

Solution 23.1

Page 41: Chapter 23 Strategy

41

The Implementing Classes

• The PromotionAdvisor and RandomAdvisor class names should be self-explanatory

• GroupAdvisor refers to the use of Rel8• ItemAdvisor refers to the use of LikeMyStuff• The implementations of the recommend()

method for these classes will wrap a call to the static methods of Rel8 and LikeMyStuff

• An expanded UML diagram for these two classes is given on the next overhead

Page 42: Chapter 23 Strategy

42

Page 43: Chapter 23 Strategy

43

Making Instances of the Implementing Classes

• An interface can’t define static methods• An interface defines what the book calls

“object methods”—methods that are called on objects

• That means that client code will have to make instances of GroupAdvisor and ItemAdvisor

• The recommend() method will be called on these objects

Page 44: Chapter 23 Strategy

44

• Only one instance each of GroupAdvisor and ItemAdvisor are needed

• In the refactored design, these instances will be static objects in the Customer class

• So the advisor objects will be “singleton like”• There won’t be an instance of each kind of

advisor for each customer

Page 45: Chapter 23 Strategy

45

• Even though the recommend() method isn’t a static method, it more or less acts like one

• If there is only one advisor object, then there is the one recommend() method that can be called on that object

• The recommend() method does something for customers

• But it does so by taking the customer as an explicit parameter rather than being called on the customer

Page 46: Chapter 23 Strategy

46

Code for the recommend() Method in the GroupAdvisor Class

• This is the recommend() method in the GroupAdvisor class:

• public Firework recommend(Customer c)• {• return (Firework) Rel8.advise(c);• }

• It wraps a call to the advise() method of Rel8• In essence, the call is adapted to the recommend()

interface of Advisor

Page 47: Chapter 23 Strategy

47

Code for the recommend() Method in the ItemAdvisor Class

• The code for the recommend() method in the ItemAdvisor class is analogous.

• The book doesn’t give it and it doesn’t even bother to give it as a challenge.

• It should be straightforward to write that method.

Page 48: Chapter 23 Strategy

48

• Challenge 23.2• “In addition to Strategy, what pattern appears

in the GroupAdvisor and ItemAdvisor classes?”

• [The answer to this was given away in the last remark about the recommend() code in GroupAdvisor.]

Page 49: Chapter 23 Strategy

49

• Solution 23.2• “The GroupAdvisor and ItemAdvisor classes

are instances of Adapter, providing the interface a client expects, using the services of a class with a different interface.”

Page 50: Chapter 23 Strategy

50

Code for the recommend() Method in the PromotionAdvisor Class

• A PromotionAdvisor class is also needed, with a recommend() method

• On the one hand, promotion should be a simple case

• On the other hand, the book puts a lot of detail into the implementation

Page 51: Chapter 23 Strategy

51

• Most of the logic of the original code is moved into the constructor for the new class

• If a promotion is on, then the promoted instance variable of the class is initialized

• In addition to the recommend() method, there is a hasItem() method which can be called to see whether a promoted item is available

Page 52: Chapter 23 Strategy

52

• The book’s implementation makes use of class loading logic

• This requires try/catch blocks• The details of this technique will not be

covered since they are extraneous to the design pattern

• The code is shown on the following overheads

Page 53: Chapter 23 Strategy

53

• public class PromotionAdvisor implements Advisor • {• private Firework promoted;• public PromotionAdvisor() • {• try • {• Properties p = new Properties();•

p.load(ClassLoader.getSystemResourceAsStream("config/strategy.dat"));• String promotedFireworkName = p.getProperty("promote");• if (promotedFireworkName != null) • promoted = Firework.lookup(promotedFireworkName);• } • catch (Exception ignored) • {• // Resource not found or failed to load• promoted = null;• }• }

Page 54: Chapter 23 Strategy

54

• public boolean hasItem() • {• return promoted != null;• }• public Firework recommend(Customer c) • {• return promoted;• }• }

Page 55: Chapter 23 Strategy

55

Code for the recommend() Method in the RandomAdvisor Class

• The RandomAdvisor class is simple• Its code is shown on the following overhead

Page 56: Chapter 23 Strategy

56

• public class RandomAdvisor implements Advisor • {• public Firework recommend(Customer c) • {• return Firework.getRandom();• }• }

Page 57: Chapter 23 Strategy

57

Refactoring the Customer Class to Use the Interface

Page 58: Chapter 23 Strategy

58

Creating the Advisor Objects

• A single instance of each kind of advisor is created in the new Customer2 class

• For any given customer, recommend() may be called on one of these advisor objects

• The code for the new customer class, Customer2, begins by creating these objects

• This code is shown on the following overhead

Page 59: Chapter 23 Strategy

59

• private static PromotionAdvisor promotionAdvisor =

• new PromotionAdvisor();

• private static GroupAdvisor groupAdvisor =• new GroupAdvisor();

• private static ItemAdvisor itemAdvisor =• new ItemAdvisor();

• private static RandomAdvisor randomAdvisor =• new RandomAdvisor();

Page 60: Chapter 23 Strategy

60

Implementing the getAdvisor() Method

• Customer2 contains a method named getAdvisor() for picking which kind of advisor to use

• The original design had if/else statements in which different strategies were called

• In the new design you don’t eliminate if/else statements, but they appear in a different place

Page 61: Chapter 23 Strategy

61

• In the new design the if/else logic is implemented in the getAdvisor() method

• getAdvisor() returns an advisor object• Polymorphism and dynamic binding

determine which strategy is used when recommend() is called on the advisor object

Page 62: Chapter 23 Strategy

62

How the getAdvisor() Method Works

• Recall that getAdvisor() is in the Customer2 class

• Its implementation includes a call to hasItem(), mentioned earlier to check for a promotion

• Its implementation also includes calls to isRegistered() and isBigSpender() on the implicit customer parameter to determine if the advisor should be Rel8 or LikeMyStuff

Page 63: Chapter 23 Strategy

63

• getAdvisor() does lazy initialization of the advisor

• The value of the advisor instance variable is only set at the time the getAdvisor() method is called

• It’s not lazy construction because one instance of each kind of advisor has already been created at the top of Customer2

• The code is shown on the following overhead

Page 64: Chapter 23 Strategy

64

• private Advisor getAdvisor() • {• if (advisor == null) • {• if (promotionAdvisor.hasItem())• advisor = promotionAdvisor;• else if (isRegistered())• advisor = groupAdvisor;• else if (isBigSpender())• advisor = itemAdvisor;• else• advisor = randomAdvisor;• }• return advisor;• }

Page 65: Chapter 23 Strategy

65

The getRecommended() Method in Customer2

• Challenge 23.3• “Write the new code for

Customer.getRecommended().”• Comment mode on:• It may be helpful to step back and review

where we’re at in the redesign• The UML for the redesign is repeated on the

following overhead

Page 66: Chapter 23 Strategy

66

Page 67: Chapter 23 Strategy

67

• We’ve got the 4 advisor classes• We’ve got the getAdvisor() method• The final ingredient of the new design is the

getRecommended() method in the Customer2 class

• This code should rely on the advisor for the customer, and a call to the recommend() method on that advisor

• The code is shown on the following overhead

Page 68: Chapter 23 Strategy

68

Solution 23.3

• Your code should look something like:• public Firework getRecommended()• {• return getAdvisor().recommend(this);• }

Page 69: Chapter 23 Strategy

69

The Benefit of the Design Pattern

• It is apparent that some of the code in the application is simplified by the application of the design pattern

• Polymorphism and dynamic binding determines which version of recommend() will be used depending on the type of advisor that was initialized earlier.

Page 70: Chapter 23 Strategy

70

Comparing Strategy and State

• In the book State and Strategy are presented one after the other

• These patterns have some structural similarities and the book compares them

• The similarities can be summarized by looking at the UML diagram for state again

• It is shown on the following overhead

Page 71: Chapter 23 Strategy

71

Page 72: Chapter 23 Strategy

72

• In both patterns there is a client that makes use of an interface/abstract class

• Each implementing class/subclass contains a method of the same name

• In the client, the method is called on an object and polymorphism/dynamic binding determines which version of the method is called

Page 73: Chapter 23 Strategy

73

• Just like the adapter, this structure will appear again in other patterns

• Using the book’s terminology, the design patterns under consideration which share this structure are different patterns because their intents differ

• In other words, what you accomplish by using the structure is not the same

Page 74: Chapter 23 Strategy

74

• It is quite apparent at the detailed level that getting a recommended firework in no way causes a customer to transition into a different state

• However, touching the control button on the carousel door caused it to enter a different state

• This important kind of difference isn’t apparent from looking at the overall structure at a macro level in a UML diagram

Page 75: Chapter 23 Strategy

75

Comparing Strategy and Template Method (A Sideshow?)

• This section is not critically important• There may be some worthwhile ideas

presented, but it doesn’t help too much in focusing on what the strategy design pattern is

• It’s really more focused on showing that the template design pattern is not the same as the strategy design pattern

Page 76: Chapter 23 Strategy

76

• The book compares the Strategy and Template methods

• In this case the similarities that the book suggests might exist are not illustrated by a UML diagram

• The authors are directly addressing the question of whether Strategy and Template can be viewed as having the same intent

Page 77: Chapter 23 Strategy

77

• Recall the first presentation of the Template Method design pattern

• The template was a sort() method in the Arrays or Collections class

• What was stubbed in was the pairwise comparison operation for elements of the data structure

Page 78: Chapter 23 Strategy

78

• The authors state that you might argue that changing the pairwise comparison step changes the strategy of sorting

• They illustrate this idea by suggesting that sorting rockets by price rather than by thrust would support a different marketing strategy

• Observe that the claim about strategy in this argument is about something in the problem domain, marketing, not in the code writing

Page 79: Chapter 23 Strategy

79

• Challenge 23.4• “Provide an argument that the Arrays.sort() method

provides an example of Template Method or that it is an example of Strategy.”

• Comment mode on:• It’s clear that the book thinks sorting is an example of

template, not strategy, since sorting was covered in the template unit.

• I agree with its reasoning, as presented in the second of the following arguments

Page 80: Chapter 23 Strategy

80

• Solution 23.4• “Is a reusable sort routine an example of

Template Method or of Strategy?”• [See the following overheads.]

Page 81: Chapter 23 Strategy

81

An Argument that Sorting is an Example of the Strategy Design Pattern

• “Template Method, according to the original Design Patterns book, lets “subclasses” redefine certain steps of an algorithm.

• But the Collections.sort() method doesn’t work with subclasses; it uses a Comparator instance.

• Each instance of Comparator provides a new method and thus a new algorithm and a new strategy.

• The sort() method is a good example of Strategy.

Page 82: Chapter 23 Strategy

82

An Argument that Sorting is an Example of the Template Design Pattern

• There are many sorting algorithms, but Collections.sort() uses only one (QuickSort).

• Changing the algorithm would mean changing to, say, a heap sort or a bubble sort.

• The intent of Strategy is to let you plug in different algorithms.

• That doesn’t happen here.• The intent of Template Method is to let you plug a step

into an algorithm.• That is precisely how the sort() method works.”

Page 83: Chapter 23 Strategy

83

• The book’s argument is good—but maybe not entirely clear.

• The point is that at the macro level, a choice among strategies would mean a choice between different sorting algorithms

• At the micro level, choosing between pairwise comparisons doesn’t change the overall strategy

• It is an example of applying the template pattern

Page 84: Chapter 23 Strategy

84

Another Example

• The other example is based on cups and seeds in Togiz Kumalak

• One side of a Togiz Kumalak board, consisting of 9 cups, is initialized with random seed counts and presented on the screen

• This half of the board belongs to player whose turn it is

• The player has to choose which cup to play

Page 85: Chapter 23 Strategy

85

• The application implements 3 different strategies:

• Play a cup at random• Play the cup with the minimum number of

seeds• Play the cup with the maximum number of

seeds

Page 86: Chapter 23 Strategy

86

• The player is prompted to pick a strategy• The application then tells which cup to play

based on that strategy• The application is illustrated in the screenshot

on the following overhead

Page 87: Chapter 23 Strategy

87

Page 88: Chapter 23 Strategy

88

• The code for this example application is not presented in the overheads

• It is available on the course Web page in case you’re interested

• You will find it is an extremely simple implementation of the strategy design pattern as presented in the book

Page 89: Chapter 23 Strategy

89

UML for the Pattern

• The UML diagram given earlier is repeated on the following overhead

• It is specific to the fireworks problem, but otherwise it shows what the pattern is about

• It might be possible to make this and other patterns clearer by including sequence diagrams

• It would show how the getRecommended() method makes a call to the recommend() method

Page 90: Chapter 23 Strategy

90

Page 91: Chapter 23 Strategy

91

A UML Diagram for the Pattern from Lasater

• Lasater’s UML diagram is given on the following overhead

• It is useful, as usual, because it uses generic names for the classes in the pattern

• This one is also useful because it shows that you could use an abstract class just as easily as you could use an interface when applying the pattern

Page 92: Chapter 23 Strategy

92

Page 93: Chapter 23 Strategy

93

Summary

• Multiple strategies may appear in a single method

• This can be an unwieldy design• A solution is to implement each separate

strategy as a method of the same name in different classes

• The individual implementations will be simpler

Page 94: Chapter 23 Strategy

94

• The original design would have logic to pick one of the strategies

• The new design would also contain such logic somewhere, but at least it is separated from the implementations of the strategies

• The new logic will be based on which of the strategy classes is constructed

• It would be reasonable to hold the strategy object as a reference in a client class

Page 95: Chapter 23 Strategy

95

• Then at the appropriate time, this object has the strategy method called on it

• In other words, once the object choice is made, the method choice is accomplished by polymorphism and dynamic binding

• The result of this kind of design is individual pieces of code that are smaller, simpler, and unified in purpose

Page 96: Chapter 23 Strategy

96

• Overall, the design should be clearer, with different strategies implemented in different classes

• The cleaner the design, the less commenting may be needed…

Page 97: Chapter 23 Strategy

97

The End