CS 350 – Software Design The Strategy Pattern – Chapter 9 Changes to software, like other things in life, often focus on the immediate concerns and ignore the longer term. Two common approaches: Overanalyze and overdesign: Analysis paralysis Jump right in Somewhere in between is the ideal. This is why I feel the argument in Software Engineering about Agile methodologies vs. traditional waterfall development is silly. It should always be a combination. In addition, a key element is to be wise enough to DESIGN FOR CHANGE. Simple to say, no so intuitive (at first) to do. With practice, it’s not that difficult.
CS 350 – Software Design The Strategy Pattern – Chapter 9 We do not anticipate the exact change, instead we anticipate what may change. New Case Study: E-Commerce System The company is located in the US, but its business has an international scope A Task controller object handles sales request and passes it to the SalesOrder object to process the order.
CS 350 – Software Design The Strategy Pattern – Chapter 9 The functions for SalesOrder include the following: Allow for filling out the order with a GUI Handle tax calculations Process the order and print a sales receipt Some object will be implemented with the help of other objects SalesOrder will not print itself
CS 350 – Software Design The Strategy Pattern – Chapter 9 What happens when requirements change? Perhaps a new requirement for taxation rules is added. Handle taxation for countries outside the United States. Thus, we need to add new rules for computing taxes.
CS 350 – Software Design The Strategy Pattern – Chapter 9 How do we handle different implementations of tasks that are pretty much conceptually the same? Copy and paste Switches/Ifs on variable specifying the case we have Use function pointers (a different one representing each case) Inheritance Delegate the entire functionality to a new object
CS 350 – Software Design The Strategy Pattern – Chapter 9 Copy / Paste Traditional method Copy something that works, paste it somewhere else, make a changes. Maintenance headaches Switches Issues with coupling, testing More importantly, what happens when you have multiple variations?
CS 350 – Software Design The Strategy Pattern – Chapter 9 Simple Cases – Two Countries // Handle Tax switch (myNation) { case US: //US Tax Rules here break; case Canada: //Canadian Tax Rules here } //Handle Currency //US Currency Rules here //Canadian Currency Rules here //Handle Date Format //US Date Format Rules here //Canadian Date Format Rules here
CS 350 – Software Design The Strategy Pattern – Chapter 9 Add a Third Country – Still a “Clean” implementation // Handle Tax switch (myNation) { case US: //US Tax Rules here break; case Canada: //Canadian Tax Rules here case Germany: //Germany Tax Rules here } //Handle Currency //US Currency Rules here //Canadian Currency Rules here //Germany Currency Rules here
CS 350 – Software Design The Strategy Pattern – Chapter 9 Add a Third Country – Still a “Clean” implementation You may need to add another switch // Handle Language switch (myNation) { case US: case Canada: //use English break; case Germany: //use German }
CS 350 – Software Design The Strategy Pattern – Chapter 9 Variations “dirty” the implementation // Handle Language switch (myNation) { case Canada: if (inQuebec) { //use French break;} else //use English break; case Germany: //use German } Flow of the switches is hard to read When new cases come in, you must find every place it can be involved Called Switch Creep
CS 350 – Software Design The Strategy Pattern – Chapter 9 Function Pointers Nice Compact Can’t retain state on a per-object basis Inheritance Nothing really wrong with it per say Certainly allows reuse Could create new SalesOrder objects from existing objects
CS 350 – Software Design The Strategy Pattern – Chapter 9 Inheritance What happens when things vary independently? Too many classes! Thing of the German example where we may vary data format, language, and freight rules
CS 350 – Software Design The Strategy Pattern – Chapter 9 A Better Approach Find out what varies and encapsulate it in a class of its own. Contain this class in another class. What varies in this example? Tax rules, therefore create an abstract class that defines how to accomplish taxation conceptually.
CS 350 – Software Design The Strategy Pattern – Chapter 9 A Better Approach Now use aggregation to give the SalesOrder object the ability to handle Tax.
CS 350 – Software Design The Strategy Pattern – Chapter 9 public abstract class CalcTax { abstract public double taxAmount(long itemSold, double price); } Public class CanTax extends CalcTax { public double TaxAmount (long itemSold, double price){ //in real life, figure out tax according to the rules in Canada and return it //here return 0 so this will compile return 0.0; } Public class USTax extends CalcTax { //in real life, figure out tax according to the rules in the US and return it
CS 350 – Software Design The Strategy Pattern – Chapter 9 public class SalesOrder { public void process (CalcTax taxToUse) { long itemNumber=0; double price=0; //given the tax object to use, calculate the tax double tax = taxToUse.taxAmount(itemNumber, price); } public class TaskController { public void process() { // this code is an emulation of a processing task controller // figure out what country you are in CalcTax myTax; myTax = getTaxRulesForCountry(); SalesOrder mySO = new SalesOrder(); mySO.process(myTax);
CS 350 – Software Design The Strategy Pattern – Chapter 9 A Better Approach
CS 350 – Software Design The Strategy Pattern – Chapter 9 So What’s the Difference? Looking at it quickly, it appears we just pushed the problem down the chain. The key difference is that in the original solution, there was one large hierarchy containing all the variation. The improved solution has a few, smaller, independent hierarchies. Also other pieces of the system can use the smaller object hierarchies we created.
CS 350 – Software Design The Strategy Pattern – Chapter 9 Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. The Strategy Pattern is based on a few principles: Objects have responsibilities Different specific implementations of these responsibilities are manifested through the use of polymorphism There is a need to manage several different implementations of the same basic algorithm. It is good design practice to separate behaviors that occur in the same problem domain from each other.
CS 350 – Software Design The Strategy Pattern – Chapter 9 Intent: Enable you to use different business rules or algorithms depending on the context in which they occur. Problem: The selection of an algorithm that needs to be applied depends on the client making the request or the data being acted on. Solution: Separate the selection of the algorithm from the implementation of the algorithm.
CS 350 – Software Design The Strategy Pattern – Chapter 9 Implementation: Have the class that uses the algorithm (Context) contain an abstract class (Strategy) that has an abstract method specifying how to call the algorithm. Each derived class implements the algorithm needed.