97
Chapter 23 Strategy Summary prepared by Kirk Scott 1

Chapter 23 Strategy

  • Upload
    glenda

  • View
    38

  • Download
    0

Embed Size (px)

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

Citation preview

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