unit 18 strategy

96
Unit 18 Strategy Summary prepared by Kirk Scott 1

Upload: hina

Post on 16-Feb-2016

44 views

Category:

Documents


0 download

DESCRIPTION

Unit 18 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

Page 1: Unit 18 Strategy

1

Unit 18Strategy

Summary prepared by Kirk Scott

Page 2: Unit 18 Strategy

2

Page 3: Unit 18 Strategy

3

Page 4: Unit 18 Strategy

4

Design Patterns in JavaChapter 23

Strategy

Summary prepared by Kirk Scott

Page 5: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 Strategy

14

Promoted Firework

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

recommend it

Page 15: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 Strategy

19

Page 20: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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: Unit 18 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()• 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 26: Unit 18 Strategy

26

Doing the Default

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

Page 27: Unit 18 Strategy

27

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 28: Unit 18 Strategy

28

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 29: Unit 18 Strategy

29

• 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 30: Unit 18 Strategy

30

• // 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 31: Unit 18 Strategy

31

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 32: Unit 18 Strategy

32

• 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 33: Unit 18 Strategy

33

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 34: Unit 18 Strategy

34

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 35: Unit 18 Strategy

35

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 36: Unit 18 Strategy

36

Page 37: Unit 18 Strategy

37

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 38: Unit 18 Strategy

38

• 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 39: Unit 18 Strategy

39

Solution 23.1

Page 40: Unit 18 Strategy

40

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 41: Unit 18 Strategy

41

Page 42: Unit 18 Strategy

42

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 43: Unit 18 Strategy

43

• 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 44: Unit 18 Strategy

44

• 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 45: Unit 18 Strategy

45

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 46: Unit 18 Strategy

46

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 47: Unit 18 Strategy

47

• 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 48: Unit 18 Strategy

48

• 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 49: Unit 18 Strategy

49

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 50: Unit 18 Strategy

50

• 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 51: Unit 18 Strategy

51

• 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 52: Unit 18 Strategy

52

• 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 53: Unit 18 Strategy

53

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

Page 54: Unit 18 Strategy

54

Code for the recommend() Method in the RandomAdvisor Class

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

Page 55: Unit 18 Strategy

55

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

Page 56: Unit 18 Strategy

56

Refactoring the Customer Class to Use the Interface

Page 57: Unit 18 Strategy

57

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 58: Unit 18 Strategy

58

• 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 59: Unit 18 Strategy

59

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 60: Unit 18 Strategy

60

• 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 61: Unit 18 Strategy

61

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 62: Unit 18 Strategy

62

• 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 63: Unit 18 Strategy

63

• 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 64: Unit 18 Strategy

64

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 65: Unit 18 Strategy

65

Page 66: Unit 18 Strategy

66

• 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 67: Unit 18 Strategy

67

Solution 23.3

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

Page 68: Unit 18 Strategy

68

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 69: Unit 18 Strategy

69

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 70: Unit 18 Strategy

70

Page 71: Unit 18 Strategy

71

• 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 72: Unit 18 Strategy

72

• 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 73: Unit 18 Strategy

73

• 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 74: Unit 18 Strategy

74

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 75: Unit 18 Strategy

75

• The book compares the Strategy and Template methods

• In this case the similarities that 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 76: Unit 18 Strategy

76

• 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 77: Unit 18 Strategy

77

• 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 78: Unit 18 Strategy

78

• 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 79: Unit 18 Strategy

79

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

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

Page 80: Unit 18 Strategy

80

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 81: Unit 18 Strategy

81

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 82: Unit 18 Strategy

82

• 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 83: Unit 18 Strategy

83

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 84: Unit 18 Strategy

84

• 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 85: Unit 18 Strategy

85

• 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 86: Unit 18 Strategy

86

Page 87: Unit 18 Strategy

87

• 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 88: Unit 18 Strategy

88

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 89: Unit 18 Strategy

89

Page 90: Unit 18 Strategy

90

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 91: Unit 18 Strategy

91

Page 92: Unit 18 Strategy

92

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 93: Unit 18 Strategy

93

• 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 94: Unit 18 Strategy

94

• 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 95: Unit 18 Strategy

95

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

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

Page 96: Unit 18 Strategy

96

The End