SlideShare a Scribd company logo
Design Patterns 05/27/10 Week 2: Strategy and Template Jonathan Simon [email_address]
Agenda Strategy Pattern SimUDuck Application (Head First) Setting Behavior Dynamically Favor Composition over Inheritance Lab Refactoring w/Strategy Dependency Injection Template Pattern Hooks Hollywood Principle 05/27/10
SimUDuck Application  (Head First Design Patterns) pg 2 in book. Duck can  Quack Swim Display – handles visual display It is assumed that all Ducks have the same behavior for Quack and Swim. 05/27/10
SimUDuck Application pg 3 Now fly() behavior is added to the superclass.  This is a new requirement! Problem since RubberDucks don’t fly!  pg 4-5. How can this problem be solved? We could override fly() in RubberDuck to do nothing. Also note that RubberDucks do not quack..they Squeak. What was good for reuse is bad for maintenance. Note: a change to the superclass unintentionally can affect all subclasses.  You would have to inspect each subclass. 05/27/10
Using Interface pg 6 – we learn that the superclass flying and quacking behavior will constantly change (due to changing customer requirements) What would need to happen every time the behavior changed? Joe creates a Flyable and Quackable interface and applies it to the classes which has those behaviors. He pulls Fly and Quack out of the superclass. How will each Duck sublcass define those behaviors?  Could there be possible duplication of code? Ie, MallardDuck’s implementation of fly() versus RedheadDuck’s implementation. What if there are different variations of flying? 05/27/10
The problem… Inheritance didn’t work  Not all subclasses need to Fly or Quack.  Making a change to superclass will cause a maintenance headache. Flyable/Quackable interface didn’t work No code re-use among the different Fly/Quack behaviors. If Fly changed, you would need to track down all subclasses that use the Flyable interface. Design Principle : “Identify the aspects of your application that vary and separate them from what stays the same.” You can alter or extend parts that vary without affecting the parts that are static. 05/27/10
Back to SimUDuck Which part varies? What part does not? How can we pull out the behavior that varies from the Duck class?  Also, how can we extend this behavior in the future without having to re-write existing code? 05/27/10
Closer Look at Variable Behavior pg 13: Create two sets of classes (one for Flying and one for Quacking). These two sets of classes represents the behavior that varies.  We’d like the behaviors to be flexible, for example: Create a MallardDuck that can fly and quack.  But then, by a simple code change, change the MallardDuck so that it cannot fly and that when it quacks, it’s actually the song “Gimme back that Filet-O-Fish.” We don’t want the Duck class to be tied to a specific behavior of Fly or Quack. What if the Duck class was tied to an abstraction of the behavior?? 05/27/10
Design Principle #2 “ Program to an interface, not an implementation.” (I like “program to an abstraction, not an implementation.”) Define the interfaces FlyBehavior and QuackBehavior.  The Duck class will be tied to these interfaces, but not a specific implementation. Each Duck subclass will use a specific implementation of this behavior.  05/27/10
Breaking it down… pg 13.  FlyBehavior and QuackBehavior The FlyBehavior and QuackBehavior represents an abstraction of the flying and quacking. FlyWithWings, FlyNoWay, Quack, etc are implementations of these behaviors. pg 15.  The Duck class contains instance variables of FlyBehavior and QuackBehavior. Here is an example of programming to an abstraction.  The Duck class (an abstraction itself) is composed of the abstraction of two behaviors. Pg 15. performQuack function() The operation of Quacking is  delegated !  The Duck class does not do it itself. 05/27/10
Breaking it down… (cont) Pg 16.  In the constructor of MallardDuck, the quack and fly behavior is set up. Note: On pg 17, the book admits that this constructor isn’t an ideal solution. This does violate the principle of “programming to an implementation” since we are tying the MallardDuck to a specific behavior.  However, this can be changed dynamically. pg 18 Testing the Duck Code 05/27/10
Setting Behavior Dynamically  pg 20. 1. Add two new methods to Duck class 2. ModelDuck is created with some default behavior. 3. Create a new fly behavior 4. Note that ModelDuck is created..then the behavior is changed. 05/27/10
To Think About If we had used inheritance for Fly(), could you change the Fly behavior at runtime? Look at the FlyBehavior classes…what if there is common functionality amongst all of the FlyBehavior classes? Instead of an interface, use an abstract class for FlyBehavior. Think of this as a “family of algorithms” 05/27/10
Favor Composition over Inheritance Pg 23 With Composition, we were able to dynamically change behavior at runtime. With Inheritance, behavior was decided a compile time. You could not change at runtime when you use inheritance. 05/27/10
The Strategy Pattern GoF Intent: “Define a family of algorithms, encapsulate each one, and make them interchangeable.  Strategy lets the algorithm vary independently from clients that use it.” 05/27/10
Lab public class Logger  {  public void LogMessage(string message, int level) { PrintSteam[] files = OpenFiles(); WriteLogMessage(files, message, int level); CloseFiles(intfiles); }  private void WriteLogMessage(PrintStream[] files,  string message, int level) { for (int i=0; i < files.Length; i++)  { if (level == 1) { //Write error message to log file.   else if (level == 2)   //Write error message to log file + Log the    //UserName and IP address. else if (level == 3)  //Write error message to log file. + Send email to    //administrator  } }
Lab (cont) Question 1:  Which part of the code varies? Question 2: What part of the code does not vary? Question 3: Using inheritance, describe how you could isolate the parts that vary. Question 3a: (Continuing from Question 3 with inheritance) Let’s say we learn that the function OpenFiles has different behavior as well.  This behavior is completely  unrelated to the logging level.  We start by creating if/else statements inside this function.  We get in trouble from our manager for doing this since we know that there will be future change.  Can we use inheritance to fix this problem? 05/27/10
Lab (cont) Question 4: Using composition, design out how you would isolate the parts that vary.  Hint #1: Create an interface that represents the variable behavior Hint #2: Compose Logger with this variable behavior. Hint #3: Have Logger delegate to this behavior. Question 4a:  How can we change the logging level during runtime? 05/27/10
Lab (cont) Question 4b:  We get some flexibility by changing the behavior during runtime, but this also means that the person who is coding the Context object (i.e., Logger) must be aware of all possible behaviors. For example, to call setLogWriter here, you would need to be aware of LogWriter1 and LogWriter2. Logger logger = new Logger() Logger.setLogWriter(new LogWriter1()); Logger.setLogWriter(new LogWriter2()); Is there an alternative to sending an instance of LogWriter1 or LogWriter2, and yet achieve the same results? 05/27/10
Lab (cont) Question 4c: Let’s say the Logger class contains the properties LoggedInUser and LastTimeLogged.  We know  that most of the log writers (LogWriter1, LogWriter2, etc) need access to these properties.  What can we do? Bonus Question: For a Logger implementation (such as LogWriter1), how many instances do we really need? 05/27/10
Lab Answers Question 1 - In WriteLogMessage function, the if/else statement with the three different options. Question 2: The three lines of code in function LogMessage The for loop declaration in function WriteLogMessage 05/27/10
Lab Answers Question 3 public  abstract  class Logger { public void LogMessage(string message) {…} private void WriteLogMessage(PrintStream[] files, string message) { for (int i=0; i < files.Length; i++)  { WriteLogMessageImpl(PrintStream file, message); } }  protected abstract WriteLogMessageImpl(PrintStream file, string msg); } 05/27/10 Question 3a:
Lab Answers Question 4 public interface ILogWriter { void Write(PrintStream file, string message); } public class Logger {   public ILogWriter logWriter; private void WriteLogMessage(PrintStream[] files, string message) { for (int i=0; i < files.Length; i++)  { logWriter.Write(file, message); } }  } 05/27/10
Question 4a public void setLogWriter(ILogWriter writer) { this.logWriter = writer; } 05/27/10
Question 4b public enum LogWriterEnum { Simple,  Medium, Hard } public void setLogWriter(LogWriterEnum logEnum) {     if (logEnum == Simple) this.logWriter = LogWriter1(); else if (logEnum == Medium)  this.logWriter = LogWriter2(); …  } Alternative Design: http://www.codeproject.com/KB/architecture/FactoryStrategyDesignPatt.aspx 05/27/10 So what if we created an enum…
Question 4c Option 1 public interface ILogWriter { void Write(PrintStream file, string message,  string LoggedInUser, string LastTimeLogged ); } We can send the information in the method call itself.  The disadvantage is that we may be sending more information than needed. 05/27/10
Question 4c Option 2 – We can pass a reference of Context (Logger) itself public interface ILogWriter { void Write(PrintStream file, string message,  Logger log ); } Advantage  - The strategy can ask the Logger class for information that it needs. (and it may not need anything!) Disadvantage – The strategy becomes more tightly coupled with the Context object. 05/27/10
Bonus Question We can use Singletons! Instead of this code: Logger.setLogWriter(new LogWriter1()); Logger.setLogWriter(new LogWriter2()); We can use this code: Logger logger = new Logger() Logger.setLogWriter(LogWriter1.TheInstance); Logger.setLogWriter(LogWriter2.TheInstance); 05/27/10
Advantage: Unit Testing What if a new behavior is needed? Ie, new FlyBehavior, new QuackBehavior, new LogWriter, etc The new class can be created and unit tested on its own (in complete isolation of the infrastructure that uses it). Another developer who does not know the “Big Picture” can easily be given direction to create the new behavior and unit test it. 05/27/10
Refactoring w/Strategy public class SomeClass() { public void Function1() {  //section of code that does not vary  //The next line of code will vary   int i = (SOME_CONST*50)+100;   //section of code that does not vary } } 05/27/10 First question you need to ask yourself: use inheritance or composition?
Refactoring (cont) public interface IComputeStrategy { int Compute(); } public class DefaultComputeStrategy implements IComputeStrategy { public int Compute() {   return (SOME_CONST*50)+100;   } } 05/27/10
Refactoring (cont) public class SomeClass { private IComputeStrategy strategy; public SomeClass() { this.strategy = new DefaultComputeStrategy(); } public void Function1() {  //section of code that does not vary   int i = strategy.Compute();   //section of code that does not vary } } 05/27/10
Dependency Injection Technique for providing an external dependency to a software component. In the Refactoring example, SomeClass is dependent upon a concrete implementation: public SomeClass() { this.strategy = new DefaultComputeStrategy(); } But what if we did this… public SomeClass(IComputerStrategy strategy) { this.strategy = strategy; } 05/27/10
Injection References http://martinfowler.com/articles/injection.html http://msdn.microsoft.com/en-us/magazine/cc163739.aspx 05/27/10
Summary Pattern Name  – Strategy Problem  – Different algorithms will be appropriate at different times.  Need a way for an object to use different algorithms at runtime. Solution Define a family of classes that use the same interface Provide a set method so that the behavior can be set (and changed)  at runtime. Consequences Hierarchy of strategy classes Alternative to subclassing Eliminates conditional statements Clients must be aware of strategies Communication between Context and Strategy 05/27/10
Template  pg 276 contains the requirement on brewing coffee and tea. Look at code on pg 277 (Coffee) and pg 278 (Tea) How many different steps are there? What is similar? What is different? 05/27/10
Template Pg 280. Coffee’s implementation of prepareRecipe() would have to call the following: boilWater  brewCoffeeGrinds pourInCup addSugarAndMilk Tea’s implementation of prepareRecipe() would have to call the following: boilWater steepTeaBug pourInCup addLemon 05/27/10
Template Pg 282 The second step of Coffee (brewCoffeeGrinds) and the second step of Tea (steepTeaBag) can be abstracted to a function called “brew”. The last step can be abstracted to a function “addCondiments” 05/27/10
Template Pg 283 The class CaffeineBeverage contains the function prepareRecipe that contains the four steps. Note that it is marked as final. The steps brew and addCondiments have been marked as abstract. The sub-classes will specify the exact implementation of brew and addCondiments. 05/27/10
Template Method Pattern GoF Intent: “The Template Method pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses.  Template Method lets subclasses redefine certain steps of the  algorithm without changing the algorithm’s structure .” 05/27/10
Hooks “ A hook is a method that is declared in the abstract class, but only given an empty or default implementation.” Hook may be optional! Empty Implementation See pg 292 for an example.  The hook could be completely empty as well! 05/27/10
Hollywood Principle “ Don’t call us, we’ll call you.” Promotes working with abstractions as much as possible. Good for creating frameworks. 05/27/10

More Related Content

PPT
10 strategy pattern
PPT
Strategy Design Pattern
PPT
Template Method Pattern
PPT
Template Method Design Pattern
PPT
Command and Adapter Pattern
PPT
SystemVerilog OOP Ovm Features Summary
PPTX
Object Oriented Principle&rsquo;s
PPTX
Multithreading in java
10 strategy pattern
Strategy Design Pattern
Template Method Pattern
Template Method Design Pattern
Command and Adapter Pattern
SystemVerilog OOP Ovm Features Summary
Object Oriented Principle&rsquo;s
Multithreading in java

What's hot (20)

PDF
Clean code
PDF
Design Patterns Illustrated
PPTX
Multithreading in java
PPTX
2. Design patterns. part #2
PPT
Lesson10 behavioral patterns
PPT
Lesson11 more behavioural patterns
PPT
Lesson12 other behavioural patterns
ODP
Advanced junit and mockito
PPT
Oo Design And Patterns
ODP
Easymock Tutorial
PPTX
Java - Generic programming
PPTX
Interfaces in JAVA !! why??
PDF
Object Design - Part 1
PDF
JUnit & Mockito, first steps
PPT
Core java concepts
KEY
What's New In Python 2.4
KEY
What's New In Python 2.5
PPT
Effective Java - Enum and Annotations
PPTX
Java - Concurrent programming - Thread's advanced concepts
PPT
Java Tut1
Clean code
Design Patterns Illustrated
Multithreading in java
2. Design patterns. part #2
Lesson10 behavioral patterns
Lesson11 more behavioural patterns
Lesson12 other behavioural patterns
Advanced junit and mockito
Oo Design And Patterns
Easymock Tutorial
Java - Generic programming
Interfaces in JAVA !! why??
Object Design - Part 1
JUnit & Mockito, first steps
Core java concepts
What's New In Python 2.4
What's New In Python 2.5
Effective Java - Enum and Annotations
Java - Concurrent programming - Thread's advanced concepts
Java Tut1
Ad

Viewers also liked (8)

PPT
MVC and Other Design Patterns
PPT
Observer and Decorator Pattern
PPT
Factory and Abstract Factory
PPT
Introduction to Design Patterns and Singleton
PPT
Chain of responsibility
PPTX
Chain of Responsibility Pattern
PDF
How to Make Awesome SlideShares: Tips & Tricks
PDF
Getting Started With SlideShare
MVC and Other Design Patterns
Observer and Decorator Pattern
Factory and Abstract Factory
Introduction to Design Patterns and Singleton
Chain of responsibility
Chain of Responsibility Pattern
How to Make Awesome SlideShares: Tips & Tricks
Getting Started With SlideShare
Ad

Similar to Strategy and Template Pattern (20)

PPTX
Welcome to Design patterns
PPTX
L04 Software Design 2
PPTX
Design Fundamentals
PDF
L04 Software Design Examples
PPTX
Approaching Patterns How to Apply
PPT
designpatterns_blair_upe.ppt
PPT
Software Design for Testability
PPT
Introduction to Design Patterns
PPT
PDF
策略模式
PPTX
Software design principles SOLID
PDF
Object-oriented Basics
KEY
Design Patterns Course
PPT
PPTX
Design Principles
PPTX
OOP, API Design and MVP
PDF
Effective Object Oriented Design in Cpp
PPTX
Solid OOPS
PPTX
Common ASP.NET Design Patterns - Telerik India DevCon 2013
PPTX
SAD14 - The Nuts and Bolts
Welcome to Design patterns
L04 Software Design 2
Design Fundamentals
L04 Software Design Examples
Approaching Patterns How to Apply
designpatterns_blair_upe.ppt
Software Design for Testability
Introduction to Design Patterns
策略模式
Software design principles SOLID
Object-oriented Basics
Design Patterns Course
Design Principles
OOP, API Design and MVP
Effective Object Oriented Design in Cpp
Solid OOPS
Common ASP.NET Design Patterns - Telerik India DevCon 2013
SAD14 - The Nuts and Bolts

Recently uploaded (20)

PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Approach and Philosophy of On baking technology
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
KodekX | Application Modernization Development
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Machine learning based COVID-19 study performance prediction
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Spectroscopy.pptx food analysis technology
Diabetes mellitus diagnosis method based random forest with bat algorithm
Approach and Philosophy of On baking technology
Mobile App Security Testing_ A Comprehensive Guide.pdf
KodekX | Application Modernization Development
Programs and apps: productivity, graphics, security and other tools
Building Integrated photovoltaic BIPV_UPV.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Network Security Unit 5.pdf for BCA BBA.
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Machine learning based COVID-19 study performance prediction
Chapter 3 Spatial Domain Image Processing.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
The Rise and Fall of 3GPP – Time for a Sabbatical?
20250228 LYD VKU AI Blended-Learning.pptx
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Understanding_Digital_Forensics_Presentation.pptx
Encapsulation_ Review paper, used for researhc scholars
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Spectroscopy.pptx food analysis technology

Strategy and Template Pattern

  • 1. Design Patterns 05/27/10 Week 2: Strategy and Template Jonathan Simon [email_address]
  • 2. Agenda Strategy Pattern SimUDuck Application (Head First) Setting Behavior Dynamically Favor Composition over Inheritance Lab Refactoring w/Strategy Dependency Injection Template Pattern Hooks Hollywood Principle 05/27/10
  • 3. SimUDuck Application (Head First Design Patterns) pg 2 in book. Duck can Quack Swim Display – handles visual display It is assumed that all Ducks have the same behavior for Quack and Swim. 05/27/10
  • 4. SimUDuck Application pg 3 Now fly() behavior is added to the superclass. This is a new requirement! Problem since RubberDucks don’t fly! pg 4-5. How can this problem be solved? We could override fly() in RubberDuck to do nothing. Also note that RubberDucks do not quack..they Squeak. What was good for reuse is bad for maintenance. Note: a change to the superclass unintentionally can affect all subclasses. You would have to inspect each subclass. 05/27/10
  • 5. Using Interface pg 6 – we learn that the superclass flying and quacking behavior will constantly change (due to changing customer requirements) What would need to happen every time the behavior changed? Joe creates a Flyable and Quackable interface and applies it to the classes which has those behaviors. He pulls Fly and Quack out of the superclass. How will each Duck sublcass define those behaviors? Could there be possible duplication of code? Ie, MallardDuck’s implementation of fly() versus RedheadDuck’s implementation. What if there are different variations of flying? 05/27/10
  • 6. The problem… Inheritance didn’t work Not all subclasses need to Fly or Quack. Making a change to superclass will cause a maintenance headache. Flyable/Quackable interface didn’t work No code re-use among the different Fly/Quack behaviors. If Fly changed, you would need to track down all subclasses that use the Flyable interface. Design Principle : “Identify the aspects of your application that vary and separate them from what stays the same.” You can alter or extend parts that vary without affecting the parts that are static. 05/27/10
  • 7. Back to SimUDuck Which part varies? What part does not? How can we pull out the behavior that varies from the Duck class? Also, how can we extend this behavior in the future without having to re-write existing code? 05/27/10
  • 8. Closer Look at Variable Behavior pg 13: Create two sets of classes (one for Flying and one for Quacking). These two sets of classes represents the behavior that varies. We’d like the behaviors to be flexible, for example: Create a MallardDuck that can fly and quack. But then, by a simple code change, change the MallardDuck so that it cannot fly and that when it quacks, it’s actually the song “Gimme back that Filet-O-Fish.” We don’t want the Duck class to be tied to a specific behavior of Fly or Quack. What if the Duck class was tied to an abstraction of the behavior?? 05/27/10
  • 9. Design Principle #2 “ Program to an interface, not an implementation.” (I like “program to an abstraction, not an implementation.”) Define the interfaces FlyBehavior and QuackBehavior. The Duck class will be tied to these interfaces, but not a specific implementation. Each Duck subclass will use a specific implementation of this behavior. 05/27/10
  • 10. Breaking it down… pg 13. FlyBehavior and QuackBehavior The FlyBehavior and QuackBehavior represents an abstraction of the flying and quacking. FlyWithWings, FlyNoWay, Quack, etc are implementations of these behaviors. pg 15. The Duck class contains instance variables of FlyBehavior and QuackBehavior. Here is an example of programming to an abstraction. The Duck class (an abstraction itself) is composed of the abstraction of two behaviors. Pg 15. performQuack function() The operation of Quacking is delegated ! The Duck class does not do it itself. 05/27/10
  • 11. Breaking it down… (cont) Pg 16. In the constructor of MallardDuck, the quack and fly behavior is set up. Note: On pg 17, the book admits that this constructor isn’t an ideal solution. This does violate the principle of “programming to an implementation” since we are tying the MallardDuck to a specific behavior. However, this can be changed dynamically. pg 18 Testing the Duck Code 05/27/10
  • 12. Setting Behavior Dynamically pg 20. 1. Add two new methods to Duck class 2. ModelDuck is created with some default behavior. 3. Create a new fly behavior 4. Note that ModelDuck is created..then the behavior is changed. 05/27/10
  • 13. To Think About If we had used inheritance for Fly(), could you change the Fly behavior at runtime? Look at the FlyBehavior classes…what if there is common functionality amongst all of the FlyBehavior classes? Instead of an interface, use an abstract class for FlyBehavior. Think of this as a “family of algorithms” 05/27/10
  • 14. Favor Composition over Inheritance Pg 23 With Composition, we were able to dynamically change behavior at runtime. With Inheritance, behavior was decided a compile time. You could not change at runtime when you use inheritance. 05/27/10
  • 15. The Strategy Pattern GoF Intent: “Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.” 05/27/10
  • 16. Lab public class Logger { public void LogMessage(string message, int level) { PrintSteam[] files = OpenFiles(); WriteLogMessage(files, message, int level); CloseFiles(intfiles); } private void WriteLogMessage(PrintStream[] files, string message, int level) { for (int i=0; i < files.Length; i++) { if (level == 1) { //Write error message to log file. else if (level == 2) //Write error message to log file + Log the //UserName and IP address. else if (level == 3) //Write error message to log file. + Send email to //administrator } }
  • 17. Lab (cont) Question 1: Which part of the code varies? Question 2: What part of the code does not vary? Question 3: Using inheritance, describe how you could isolate the parts that vary. Question 3a: (Continuing from Question 3 with inheritance) Let’s say we learn that the function OpenFiles has different behavior as well. This behavior is completely unrelated to the logging level. We start by creating if/else statements inside this function. We get in trouble from our manager for doing this since we know that there will be future change. Can we use inheritance to fix this problem? 05/27/10
  • 18. Lab (cont) Question 4: Using composition, design out how you would isolate the parts that vary. Hint #1: Create an interface that represents the variable behavior Hint #2: Compose Logger with this variable behavior. Hint #3: Have Logger delegate to this behavior. Question 4a: How can we change the logging level during runtime? 05/27/10
  • 19. Lab (cont) Question 4b: We get some flexibility by changing the behavior during runtime, but this also means that the person who is coding the Context object (i.e., Logger) must be aware of all possible behaviors. For example, to call setLogWriter here, you would need to be aware of LogWriter1 and LogWriter2. Logger logger = new Logger() Logger.setLogWriter(new LogWriter1()); Logger.setLogWriter(new LogWriter2()); Is there an alternative to sending an instance of LogWriter1 or LogWriter2, and yet achieve the same results? 05/27/10
  • 20. Lab (cont) Question 4c: Let’s say the Logger class contains the properties LoggedInUser and LastTimeLogged. We know that most of the log writers (LogWriter1, LogWriter2, etc) need access to these properties. What can we do? Bonus Question: For a Logger implementation (such as LogWriter1), how many instances do we really need? 05/27/10
  • 21. Lab Answers Question 1 - In WriteLogMessage function, the if/else statement with the three different options. Question 2: The three lines of code in function LogMessage The for loop declaration in function WriteLogMessage 05/27/10
  • 22. Lab Answers Question 3 public abstract class Logger { public void LogMessage(string message) {…} private void WriteLogMessage(PrintStream[] files, string message) { for (int i=0; i < files.Length; i++) { WriteLogMessageImpl(PrintStream file, message); } } protected abstract WriteLogMessageImpl(PrintStream file, string msg); } 05/27/10 Question 3a:
  • 23. Lab Answers Question 4 public interface ILogWriter { void Write(PrintStream file, string message); } public class Logger { public ILogWriter logWriter; private void WriteLogMessage(PrintStream[] files, string message) { for (int i=0; i < files.Length; i++) { logWriter.Write(file, message); } } } 05/27/10
  • 24. Question 4a public void setLogWriter(ILogWriter writer) { this.logWriter = writer; } 05/27/10
  • 25. Question 4b public enum LogWriterEnum { Simple, Medium, Hard } public void setLogWriter(LogWriterEnum logEnum) { if (logEnum == Simple) this.logWriter = LogWriter1(); else if (logEnum == Medium) this.logWriter = LogWriter2(); … } Alternative Design: http://www.codeproject.com/KB/architecture/FactoryStrategyDesignPatt.aspx 05/27/10 So what if we created an enum…
  • 26. Question 4c Option 1 public interface ILogWriter { void Write(PrintStream file, string message, string LoggedInUser, string LastTimeLogged ); } We can send the information in the method call itself. The disadvantage is that we may be sending more information than needed. 05/27/10
  • 27. Question 4c Option 2 – We can pass a reference of Context (Logger) itself public interface ILogWriter { void Write(PrintStream file, string message, Logger log ); } Advantage - The strategy can ask the Logger class for information that it needs. (and it may not need anything!) Disadvantage – The strategy becomes more tightly coupled with the Context object. 05/27/10
  • 28. Bonus Question We can use Singletons! Instead of this code: Logger.setLogWriter(new LogWriter1()); Logger.setLogWriter(new LogWriter2()); We can use this code: Logger logger = new Logger() Logger.setLogWriter(LogWriter1.TheInstance); Logger.setLogWriter(LogWriter2.TheInstance); 05/27/10
  • 29. Advantage: Unit Testing What if a new behavior is needed? Ie, new FlyBehavior, new QuackBehavior, new LogWriter, etc The new class can be created and unit tested on its own (in complete isolation of the infrastructure that uses it). Another developer who does not know the “Big Picture” can easily be given direction to create the new behavior and unit test it. 05/27/10
  • 30. Refactoring w/Strategy public class SomeClass() { public void Function1() { //section of code that does not vary //The next line of code will vary int i = (SOME_CONST*50)+100; //section of code that does not vary } } 05/27/10 First question you need to ask yourself: use inheritance or composition?
  • 31. Refactoring (cont) public interface IComputeStrategy { int Compute(); } public class DefaultComputeStrategy implements IComputeStrategy { public int Compute() { return (SOME_CONST*50)+100; } } 05/27/10
  • 32. Refactoring (cont) public class SomeClass { private IComputeStrategy strategy; public SomeClass() { this.strategy = new DefaultComputeStrategy(); } public void Function1() { //section of code that does not vary int i = strategy.Compute(); //section of code that does not vary } } 05/27/10
  • 33. Dependency Injection Technique for providing an external dependency to a software component. In the Refactoring example, SomeClass is dependent upon a concrete implementation: public SomeClass() { this.strategy = new DefaultComputeStrategy(); } But what if we did this… public SomeClass(IComputerStrategy strategy) { this.strategy = strategy; } 05/27/10
  • 34. Injection References http://martinfowler.com/articles/injection.html http://msdn.microsoft.com/en-us/magazine/cc163739.aspx 05/27/10
  • 35. Summary Pattern Name – Strategy Problem – Different algorithms will be appropriate at different times. Need a way for an object to use different algorithms at runtime. Solution Define a family of classes that use the same interface Provide a set method so that the behavior can be set (and changed) at runtime. Consequences Hierarchy of strategy classes Alternative to subclassing Eliminates conditional statements Clients must be aware of strategies Communication between Context and Strategy 05/27/10
  • 36. Template pg 276 contains the requirement on brewing coffee and tea. Look at code on pg 277 (Coffee) and pg 278 (Tea) How many different steps are there? What is similar? What is different? 05/27/10
  • 37. Template Pg 280. Coffee’s implementation of prepareRecipe() would have to call the following: boilWater brewCoffeeGrinds pourInCup addSugarAndMilk Tea’s implementation of prepareRecipe() would have to call the following: boilWater steepTeaBug pourInCup addLemon 05/27/10
  • 38. Template Pg 282 The second step of Coffee (brewCoffeeGrinds) and the second step of Tea (steepTeaBag) can be abstracted to a function called “brew”. The last step can be abstracted to a function “addCondiments” 05/27/10
  • 39. Template Pg 283 The class CaffeineBeverage contains the function prepareRecipe that contains the four steps. Note that it is marked as final. The steps brew and addCondiments have been marked as abstract. The sub-classes will specify the exact implementation of brew and addCondiments. 05/27/10
  • 40. Template Method Pattern GoF Intent: “The Template Method pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of the algorithm without changing the algorithm’s structure .” 05/27/10
  • 41. Hooks “ A hook is a method that is declared in the abstract class, but only given an empty or default implementation.” Hook may be optional! Empty Implementation See pg 292 for an example. The hook could be completely empty as well! 05/27/10
  • 42. Hollywood Principle “ Don’t call us, we’ll call you.” Promotes working with abstractions as much as possible. Good for creating frameworks. 05/27/10

Editor's Notes

  • #2: 13 November 2008
  • #4: A duck pond simulation game. Assume that there is a screen with a pond. There are buttons for Quack, Swim, Fly, etc. You can select a Duck and say “do this”. Or you can press a button and say “All Ducks Quack”. “All Ducks Swim”. “All Ducks Fly”, etc. Also, let’s say we have a Vision Statement from the Tech Lead: be able to deploy the application once…then apply patches when needed. This patches should not affect code all ready deployed..simply extend when we already have. This will simplify re-testing everything! 13 November 2008
  • #5: Pg 2. Fly is added. This is a problem since not all Ducks fly. So if you add a new Duck to the pond, it will automatically fly when the user presses that “All Duck Fly” button. Pg 4 With Inheritance, we see that not all derived classes necessarily use the behavior of the base class (as requirements change). We could of course use more inheritance to abstract out different behaviors…but imagine what happens every time a requirements change happens? You may have to completely change your inheritance hierarchy and re-shift things around. It may be easier to just put stuff in the base class and then inherit, and then overwrite the behavior with null implementation. Inheritance implies a compile time decision. Note when happens with a DecoyDuck is added. You have to do a lot of maintenance here. 13 November 2008
  • #6: Having Fly and Quack in the superclass didn’t make sense here. Now we learn it will be changing a lot in the future. A Duck may Fly one day and then the customer says it should not fly anymore. Also, the user at runtime wants to change the behavior. 13 November 2008
  • #7: This is a very important principle. If you have an IF/ELSE block and you know that it will never never change, then it is probably good as-is. If you have an IF/ELSE and you know that there is a lot of potential change, then it is a good idea to extend. 13 November 2008
  • #8: Part that varies: Flying and Quacking Part that is the same: Displaying, Swimming Let’s pull out Fly and Quack into their own separate objects. 13 November 2008
  • #9: 13 November 2008
  • #10: Note that FlyBehavior and QuackBehavior are Interfaces. They do not need to be. What if there was a lot of common behavior behind Flying and Quacking? You may want an abstract class here instead. The basic concept here is that there an abstraction here. This is a very important concept. Think about the Singleton example I gave last week. The Singleton was tied to a specific instance of Oracle database. If you were trying to create a Common Component for your Enterprise, that Singleton would be a bad example example since it was tied to Oracle. You probably would want an object (and perhaps not a Singleton) that is designed towards an abstraction of a database. In general, this concept is key for designing frameworks or other base classes. If you are creating a base class with a lot of sub-classes, look closely. Does the base class rely on concrete implementations or abstractions?? 13 November 2008
  • #12: Pg 18 Step 1 – Abstract Duck. Note that is composed of Fly and Quack behavior. performFly and performQuack both delegate to these behaviors. Look at swim. This implies that all ducks swim. I would mark this method as final so that no one can override, else we have the same inheritance problem that we saw earlier. Look at display. It is abstract. Could we have used a Display behavior here instead?? Just like Fly and Quack??? Well, we knew that Fly and Quack will be changing a lot, so that is why we did not want to declare that behavior in the base class. Display, however, does not change. A MallardDuck will have a unique display (ie,. The image of the MallardDuck). So inheritance here is used and that is OK. Step 2 and 3 – Defines different behaviors. Note that these behaviors are a separate set of classes. There is no relation to Duck. Step 4 – what happens when mallard.performQuack() is called?? Duck.performQuack() is called It delegates to FlyBehavior.Fly(). In the case of Mallard, that is FlyWithWings.fly(). 13 November 2008
  • #13: Step 1 – these can be called at any time to change behavior! Even though we had some behavior set up in the constructor. Step 2 – we create a new type of Duck Step 3 – we create a new type of behavior Step 4 – we create a new ModelDuck. We say fly. Then we dynamically change the behavior…and then say fly again. 13 November 2008
  • #14: Big difference between Inheritance and Composition: With Inheritance, you are statically defining behavior at the time of coding. With Composition, you have the option to dynamically change behavior. The requirements can help dictate whether to use inheritance or composition. 13 November 2008
  • #15: This does not mean that Inheritance is bad! 13 November 2008
  • #17: Go through the lab together. 13 November 2008
  • #22: 13 November 2008
  • #23: You would have three classes: LogLevel1 LogLevel2 LogLevel3 Each class describes the log implementation. What is the requirement came that the log level must be changed dynamically by the user at runtime?? We would need to manage the correct LogLevel class I guess! Question 3a: Since we have already used inheritance, we really can’t use it again! We would have to use composition here…even if we don’t care about the runtime requirement. Each LogLevelXX class can use all possible behaviors of OpenFiles. If the log level does not need to change during runtime, then this implementation is fine. But if the Log Level also needs to vary during runtime, then this is not a good implementation. We would want to use composition to vary both OpenFiles and WriteLogMessage. 13 November 2008
  • #24: Hint #1 : Create an interface that represents the variable behavior Hint #2 : Compose Logger with this variable behavior. Hint #3: Have Logger delegate to this behavior. 13 November 2008
  • #25: 13 November 2008
  • #26: What is wrong with this? If you add another logwriter, you need to make two changes: Add a new entry into LogWriterEnum You need to update the setLogWriter every time you change LogWriterEnum. We could have the function talk to another object outside of Logger completely. It could ask: Give me the LogWritter object after I give you this enum. By doing this, it keeps any changes that you need to update within Logger itself. 13 November 2008
  • #30: Discuss SQL parser. I know there is change coming in different areas, for example: SQL Operator (AND, OR, etc) or how to parse a leaf node (EXISTS(XXX) or Column or Inner Query). I have coded this out into a separate class for easy extension. This also has a nice side-benefit, I could easily give the extended behavior to another developer and the developer doesn’t need to fully understand the infrastructure that code lives in. They could just focus on the new behavior. 13 November 2008
  • #32: Not Shown: A Setter 13 November 2008
  • #33: Functionally, we have not changed anything. We can use unit tests to verify. But what is wrong with the new DefaultBehavior() line? It violates the rule of programming to an interface. Alternative: create a getter(). If the strategy is null, then return a default implementation. 13 November 2008
  • #34: The new() operator for creating a new strategy is now nowhere to be seen in this class. This implies that the Client must provide the implementation. Why is this important? Imagine again the Database Object that is written to use a generic Db objects. You put this in a common component. Then different implementations can call this code with the concrete object that is needed. Also useful for unit testing for injecting a mock object. Briefly discuss the problems with Singletons…you cannot access the private constructor very easily. This idea is the basis for Spring and similar frameworks. This example is simple. 13 November 2008
  • #37: 4 steps. boilWater and pourInCup are exactly the same! The 2 nd and 4 th steps are not quite the same…but very similar. 13 November 2008
  • #38: The code does have boilWater and pourInCup in common..so that is good. That code is encapsulated in one place. What happens if a fifth step is added? You would have to change both Coffee and Tea. Is this a good design? Note that the order that these methods are called are not enforced. You could easily change the order of the four functions of Tea! What happens if a new developer comes? Is it apparent that these are the correct order of steps? 13 November 2008
  • #41: 13 November 2008