design patterns in java chapter 23 strategy

62
Design Patterns in Java Chapter 23 Strategy Summary prepared by Kirk Scott 1

Upload: fionn

Post on 16-Feb-2016

61 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Design Patterns in Java Chapter 23 Strategy

1

Design Patterns in JavaChapter 23

Strategy

Summary prepared by Kirk Scott

Page 2: Design Patterns in Java Chapter 23 Strategy

2

• 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 multiple approaches to doing something, depending on certain conditions or context

• Strategy, then, depends on picking the approach or picking the strategy

Page 3: Design Patterns in Java Chapter 23 Strategy

3

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

• Not only are there the different implementations to consider

• There is also the code that is devoted to making the choice of which strategy to use

Page 4: Design Patterns in Java Chapter 23 Strategy

4

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

• It is also to separate the code for picking the strategy from the strategy implementations

• The Strategy design pattern accomplishes this by defining a single interface for all strategies and putting the implementations for different strategies into different classes

Page 5: Design Patterns in Java Chapter 23 Strategy

5

• As you can tell from the previous description, the Strategy design pattern is another one where the intent is realized through an interface

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

Page 6: Design Patterns in Java Chapter 23 Strategy

6

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

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

Page 7: Design Patterns in Java Chapter 23 Strategy

7

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 8: Design Patterns in Java Chapter 23 Strategy

8

• The scenario for the example works like this:• 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:

• Either a particular firework is being promoted, or two pieces of software, Rel8 or LikeMyStuff can make a recommendation, or a default option can be chosen

Page 9: Design Patterns in Java Chapter 23 Strategy

9

• 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 10: Design Patterns in Java Chapter 23 Strategy

10

• 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 11: Design Patterns in Java Chapter 23 Strategy

11

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

firework is suggested at random

Page 12: Design Patterns in Java Chapter 23 Strategy

12

• 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 class 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 13: Design Patterns in Java Chapter 23 Strategy

13

Page 14: Design Patterns in Java Chapter 23 Strategy

14

• 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 15: Design Patterns in Java Chapter 23 Strategy

15

• 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

• 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 16: Design Patterns in Java Chapter 23 Strategy

16

• The Rel8 class has a method advise(), so getRecommended() wraps a call to that method if that 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 17: Design Patterns in Java Chapter 23 Strategy

17

• The LikeMyStuff class has a suggest() method, so getRecommended wraps a call to that method if that strategy is selected

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

• “this” is the customer, and LikeMyStuff relies on a database of recent purchases by that customer, which is accessed by the call to spendingSince() on the customer

Page 18: Design Patterns in Java Chapter 23 Strategy

18

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

• The code is shown on the following overheads

Page 19: Design Patterns in Java Chapter 23 Strategy

19

• 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 20: Design Patterns in Java Chapter 23 Strategy

20

• 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 21: Design Patterns in Java Chapter 23 Strategy

21

• // 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 22: Design Patterns in Java Chapter 23 Strategy

22

Refactoring to Strategy

• 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 23: Design Patterns in Java Chapter 23 Strategy

23

• 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…”

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

Page 24: Design Patterns in Java Chapter 23 Strategy

24

• Anyway, applying the Strategy design pattern to the example involves three things:

• Create an interface that defines the strategic operation

• Implement the interface with classes that represent each strategy

• Refactor the code to select and use an instance of the right strategy class

Page 25: Design Patterns in Java Chapter 23 Strategy

25

• The interface will be named Advisor• It will specify that an implementing class have

a method with these characteristics:• It will be named recommend()• It 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 26: Design Patterns in Java Chapter 23 Strategy

26

Page 27: Design Patterns in Java Chapter 23 Strategy

27

• The next step is to create the classes that represent the different strategies and implement the interface

• The book essentially presents this information as part of the following challenge

Page 28: Design Patterns in Java Chapter 23 Strategy

28

• Challenge 23.1• Fill in the class diagram in Figure 23.3, which

shows the recommendation logic refactored into a collection of strategy classes.

• Comment mode on:• What they want is mindlessly simple• That will be clear when you see the answer

Page 29: Design Patterns in Java Chapter 23 Strategy

29

Page 30: Design Patterns in Java Chapter 23 Strategy

30

• Solution 23.1• Figure B.24 shows one solution.

Page 31: Design Patterns in Java Chapter 23 Strategy

31

Page 32: Design Patterns in Java Chapter 23 Strategy

32

• In the previous diagram, the PromotionAdvisor and RandomAdvisor class names are 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 is still just a wrapped call to the static methods of Rel8 and LikeMyStuff

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

Page 33: Design Patterns in Java Chapter 23 Strategy

33

Page 34: Design Patterns in Java Chapter 23 Strategy

34

• The book notes that instances of GroupAdvisor and ItemAdvisor will be needed

• An interface can’t define static methods• An interface defines what the book calls “object methods”,

so instances of classes that implement an interface are needed in order to call the methods defined in the interface

• Only one instance each of GroupAdvisor and ItemAdvisor are needed in order to call the desired method, and in the book’s new design, these instances will be static objects in the Customer class

Page 35: Design Patterns in Java Chapter 23 Strategy

35

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

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

• By wrapping a call, recommend() in effect translates from the advise() interface of Rel8 to the recommend() interface of Advisor

Page 36: Design Patterns in Java Chapter 23 Strategy

36

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

in the GroupAdvisor and ItemAdvisor classes?

Page 37: Design Patterns in Java Chapter 23 Strategy

37

• 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.

• Comment mode on:• This wasn’t so hard—describing the wrapping

of the call as “translating” kind of gave it away

Page 38: Design Patterns in Java Chapter 23 Strategy

38

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

• 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 intialized

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

• The code is shown on the following overheads

Page 39: Design Patterns in Java Chapter 23 Strategy

39

• 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 40: Design Patterns in Java Chapter 23 Strategy

40

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

Page 41: Design Patterns in Java Chapter 23 Strategy

41

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

Page 42: Design Patterns in Java Chapter 23 Strategy

42

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

Page 43: Design Patterns in Java Chapter 23 Strategy

43

• The new customer class, Customer2, has these lines of code in it:

• private static PromotionAdvisor promotionAdvisor = new PromotionAdvisor();• private static GroupAdvisor groupAdvisor = new GroupAdvisor();• private static ItemAdvisor itemAdvisor = new ItemAdvisor();• private static RandomAdvisor randomAdvisor = new RandomAdvisor();

• In order to make use of a recommend() method, a single instance of each of the advisor classes may be needed

• The remaining logic that is needed is picking which kind of advisor to use

Page 44: Design Patterns in Java Chapter 23 Strategy

44

• Customer2 also has the method getAdvisor() in it, shown on the next overhead

• The book refers to the logic of this method as lazy-initialization

• The objects have already been created, so it’s not lazy construction, but the value of the advisor instance variable for a customer is only set at the time that you try to acquire an advisor

Page 45: Design Patterns in Java Chapter 23 Strategy

45

• 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 46: Design Patterns in Java Chapter 23 Strategy

46

• Challenge 23.3• Write the new code for

Customer.getRecommended().• Comment mode on:• In other words, write the code for the new

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

Page 47: Design Patterns in Java Chapter 23 Strategy

47

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

Page 48: Design Patterns in Java Chapter 23 Strategy

48

Comparing Strategy and State

• Recall the State design pattern example• It ended with a touch() method implemented in

several different state classes• Now compare with the Strategy design pattern

example• It ended with a recommend() method implemented

in several different advisor classes• Which version of the method was called depended on

polymorphism, the type of the object it was called on

Page 49: Design Patterns in Java Chapter 23 Strategy

49

• It is possible to argue that there is little difference between the State and Strategy design patterns

• Structurally, at least, this is the case• This has also been apparent with some of the

patterns already considered• You could draw a UML diagram of the

relationships between classes and two patterns would appear to be the same

Page 50: Design Patterns in Java Chapter 23 Strategy

50

• As usual, the book argues that the critical difference is that states and strategies have different intents

• Surely, it’s clear from the problem domains that there is a difference between transitioning between states of doors and choosing among fireworks to recommend

• The difference isn’t just one of intent

Page 51: Design Patterns in Java Chapter 23 Strategy

51

• The point of the touch() method was that calling it in one state caused you to enter another

• Calling the recommend() method on a GroupAdvisor object didn’t somehow send the application into a state where the ItemAdvisor was now appropriate

Page 52: Design Patterns in Java Chapter 23 Strategy

52

• Another way of seeing this is that in some applications it may be possible for the client to choose among several different available strategies

• By definition, when doing state, the client doesn’t choose

• The logic of the states themselves control the transition from one to another

• All in all, the book concludes that in spite of their structural similarity, State and Strategy are different

Page 53: Design Patterns in Java Chapter 23 Strategy

53

Comparing Strategy and Template Method

• Recall the first Template Method design pattern example

• 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 54: Design Patterns in Java Chapter 23 Strategy

54

• 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 55: Design Patterns in Java Chapter 23 Strategy

55

• Challenge 23.4• Provide and argument that the Arrays.sort()

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

Page 56: Design Patterns in Java Chapter 23 Strategy

56

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

Template Method or of Strategy?• Comment mode on:• It’s clear what the book thinks since it put

sorting in the Template Method chapter• I agree with its reasoning• See the answers on the following overheads

Page 57: Design Patterns in Java Chapter 23 Strategy

57

For Strategy

• 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 58: Design Patterns in Java Chapter 23 Strategy

58

For Template Method

• 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 59: Design Patterns in Java Chapter 23 Strategy

59

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 60: Design Patterns in Java Chapter 23 Strategy

60

• 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 61: Design Patterns in Java Chapter 23 Strategy

61

• 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

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

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

Page 62: Design Patterns in Java Chapter 23 Strategy

62

The End