CU-Boulder CSCI 5448 - Introduction to Design Patterns

Unformatted text preview:

Introduction to Design PatternsKenneth M. AndersonUniversity of Colorado, BoulderCSCI 4448/5448 — Lecture 16 — 10/15/2009© University of Colorado, 20091Lecture Goals• Cover Material from Chapter 1 and 2 of the Design Patterns Textbook• Introduction to Design Patterns• Strategy Pattern• Observer Pattern2Why Patterns? (I)• As the Design Guru says• “Remember, knowing concepts like•abstraction,•inheritance, and•polymorphism•do not make you a good OO designer.•A design guru thinks about how to create flexible designs that are maintainable and that can cope with change.”3Why Patterns? (II)• Someone has already solved your problems (!)• Design patterns allow you to exploit the wisdom and lessons learned by other developers who’ve encountered design problems similar to the ones you are encountering•The best way to use design patterns is to load your brain with them and then recognize places in your designs and existing applications where you can apply them•Instead of code reuse, you get experience reuse4Design Pattern by Example• SimUDuck: a “duck pond simulator” that can show a wide variety of duck species swimming and quacking• Initial State• But a request has arrived to allow ducks to also fly. (We need to stay ahead of the competition!)quack()swim()display()Duckdisplay()MallardDuckdisplay()RedheadDuck5Easyquack()swim()display()Duckdisplay()MallardDuckdisplay()RedheadDuckquack()swim()display()fly()Duckdisplay()MallardDuckdisplay()RedheadDuckCode Reuse via InheritanceAdd fly() to Duck; all ducks can now fly6Whoops!quack()swim()display()fly()Duckdisplay()MallardDuckdisplay()RedheadDuckquack()display()RubberDuckRubber ducks do not fly! They don’t quack either, so we had previously overridden quack() to make them squeak.We could override fly() in RubberDuck to make it do nothing, but that’s less than ideal, especially...7Double Whoops!quack()swim()display()fly()Duckdisplay()MallardDuckdisplay()RedheadDuckdisplay()quack()fly()RubberDuckdisplay()quack()fly()DecoyDuck…when we might always find other Duck subclasses that would have to do the same thing.What was supposed to be a good instance of reuse via inheritance has turned into a maintenance headache!8What about an Interface?swim()display()Duckdisplay()fly()quack()MallardDuckdisplay()fly()quack()RedheadDuckdisplay()quack()RubberDuckdisplay()DecoyDuckfly()Flyable«Interface»quack()Quackable«Interface»Here we define two interfaces and allow subclasses to implement the interfaces they need.What are the trade-offs?9Design Trade-Offs• With inheritance, we get• code reuse, only one fly() and quack() method vs. multiple (pro)• common behavior in root class, not so common after all (con)• With interfaces, we get• specificity: only those subclasses that need a fly() method get it (pro)• no code re-use: since interfaces only define signatures (con)• Use of abstract base class over an interface? Could do it, but only in languages that support multiple inheritance• In this approach, you implement Flyable and Quackable as abstract base classes and then have Duck subclasses use multiple inheritance• Trade-Offs?10OO Principles to the Rescue!• Encapsulate What Varies• Recall the InstrumentSpec example from the OO A&D textbook• The “what varies” part was the properties between InstrumentSpec subclasses• What we needed was “dynamic properties” and the solution entailed getting rid of all the subclasses and storing the properties in a hash table• For this particular problem, the “what varies” is the behaviors between Duck subclasses• We need to pull out behaviors that vary across subclasses and put them in their own classes (i.e. encapsulate them)• The result: fewer unintended consequences from code changes (such as when we added fly() to Duck) and more flexible code11Basic Idea• Take any behavior that varies across Duck subclasses and pull them out of Duck• Duck’s will no longer have fly() and quack() methods directly• Create two sets of classes, one that implements fly behaviors and one that implements quack behaviors• Code to an Interface• We’ll make use of the “code to an interface” principle and make sure that each member of the two sets implements a particular interface• For QuackBehavior, we’ll have Quack, Squeak, Silence• For FlyBehavior, we’ll have FlyWithWings, CantFly, FlyWhenThrown, …• Additional benefits• Other classes can gain access to these behaviors (if that makes sense) and we can add additional behaviors without impacting other classes12“Code to Interface” Does NOT Imply Java Interface• We are overloading the word “interface” when we say “code to an interface”• We can implement “code to an interface” by defining a Java interface and then have various classes implement that interface• Or, we can “code to a supertype” and instead define an abstract base class which classes can access via inheritance.• When we say “code to an interface” it implies that the object that is using the interface will have a variable whose type is the supertype (whether its an interface or abstract base class) and thus• can point at any implementation of that supertype• and is shielded from their specific class names• A Duck will point to a fly behavior with a variable of type FlyBehavior NOT FlyWithWings; the code will be more loosely coupled as a result13Bringing It All Together: Delegation• To take advantage of these new behaviors, we must modify Duck to delegate its flying and quacking behaviors to these other classes• rather than implementing this behavior internally• We’ll add two attributes that store the desired behavior and we’ll rename fly() and quack() to performFly() and performQuack()• this last step is meant to address the issue of it not making sense for a DecoyDuck to have methods like fly() and quack() directly as part of its interface• Instead, it inherits these methods and plugs-in CantFly and Silence behaviors to make sure that it does the right thing if those methods are invoked• This is an instance of the principle “Favor composition over inheritance”14New Class DiagramFlyBehavior and QuackBehavior define a set of behaviors that provide behavior to Duck. Duck is composing each set of behaviors and can switch among them dynamically, if needed. While now each subclass has a performFly() and performQuack() method, at least the user interface is uniform


View Full Document

CU-Boulder CSCI 5448 - Introduction to Design Patterns

Documents in this Course
Django

Django

42 pages

ENRS

ENRS

30 pages

PhoneGap

PhoneGap

22 pages

Load more
Download Introduction to Design Patterns
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Introduction to Design Patterns and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Introduction to Design Patterns 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?