Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced OOD and the Strategy Pattern 1. In our last episode… (It was all about Object-Oriented Design) 2.

Similar presentations


Presentation on theme: "Advanced OOD and the Strategy Pattern 1. In our last episode… (It was all about Object-Oriented Design) 2."— Presentation transcript:

1 Advanced OOD and the Strategy Pattern 1

2 In our last episode… (It was all about Object-Oriented Design) 2

3 A Concise Theory of Object-Oriented  Object represents a “thing”  person, car, date, …  (not two things, not ½ thing)  Object responds to messages  (method calls)  Things it does to itself (SRP)  That is, other objects ask the object to do something to itself  Objects are “opaque”  Can’t see each others’ data/vars  Messages (calls) are only way to get things done 3

4 A Concise Theory of Object-Oriented, II  Because objects are completely opaque, we don’t need to know what’s really inside them  Each car object could be implemented with its own unique code  If two cars behave the same, then really should have same code  Otherwise would violate DRY  And a huge amount of coding work  So all cars are made from a common car template  Template = class  The car template is not a car, it’s a “blueprint” for a car  Helps satisfy DRY 4

5 Single Responsibility Principle  S ingle R esponsibility P rinciple ( SRP )  Each class should be responsible for one thing (capability, entity, computation, etc.)  Can phrase this as “mind your own business”  object do its own calculations  object should not do calculations for another  Easy to violate this because objects need to be connected to one another  e.g., Events happen as part of Dates

6 Object-Oriented Design, “wuggy style” 6 As a user I want see my nearby friends on the map So that I know who to contact for a spontaneous meet-up class Friend { Location location(); // null −> not-known boolean online(); Bitmap image(); } class Friends implements Iterable { Friends online(); Friends locationKnown(); // −> online? } 1.Identify the “things”  me (previous user story)  friends, friend  map (previous, built-in) 2.Identify the messages  me.logged-in (previous)  friend.location-known  friend.location  friend.online  friend.near(me)  friend.image 3.Assemble into classes 4.Right things call right messages (TBD) Given I am logged in And my location is known When my friends are online And my friends’ location is known And my friends are near me Then I see them on the map

7 Object-Oriented Typing Theory of Object-Oriented, III 7

8 Typing and Subtyping: “is a”  In Object-Oriented, it’s all about behavior  A particular behavior is described by a type  Mammalian behavior is the Mammal type  Tiger behavior is the Tiger type  Because a Tiger always behaves like a Mammal, we say that Tiger is a subtype of Mammal 8 Mammal FelineCanine Tiger House Cat Feline is a subtype of Mammal House Cat is a subtype of Feline s Subtype c means all s ’s always act like a c but not all c ’s act like an s All Felines are Mammals But not all Mammals are Felines Means that Feline object will always work wherever a Mammal is needed

9 Typing and Subtyping: “is a” (II)  Feline a subtype of Mammal means Mammal a supertype of Feline  A supertype variable can hold values of any of its subtypes 9 Mammal FelineCanine Tiger House Cat void petFur(Mammal m) { int coarseness = m.furValue(); … } Use of a supertype variable like Mammal allows all current and future subtypes of Mammal to be petted petFur will work for Canine subclass Dog when it is added We say that petFur is open for extension

10 Three Ways to Declare Subtype in Java  Subclass a class  class Mammal {…} class Feline extends Mammal {…}  Feline is a subtype of Mammal  Feline gets all of Mammal ’s implementation (can override)  Subclassing abstract class is similar  Can’t “new” an abstract C b/c not all methods implemented  abstract class Mammal {…} class Feline extends Mammal {…}  Feline must implement missing methods of Mammal  Abstract class asserts “I’m a category of thing, not a real thing”  Interface has no methods implemented  Like a totally abstract class  interface Cuddly {…} class HouseCat extends Feline implements Cuddly {…} 10 Mammal Feline Canine Tiger House Cat

11 More on Interfaces  A class can extend just one superclass  But a class can implement multiple interfaces  interface Cuddly {…} interface Spotted {…} class Tabby extends Feline implements Cuddly, Spotted {…}  Means interfaces are much more flexible  Can “mix in” all the supertypes you want  Not just a tree of types anymore 11 Mammal Feline Canine Bengal Tiger Tabby Spotted Cuddly

12 More on Interfaces, II  Not all classes represent a unique type  Maybe want another impl of same thing  for performance, say  Consider two possible impl’s of Set  class TinySet implements Set { /* linked list */ } class BigSet implements Set { /* uses hard disk */ }  Identical interfaces, input/output behavior −> same type  One faster for tiny sets, the other faster for big sets  Use interfaces for implementation alternatives  Since TinySet real subtype, extends would be misleading  Since no shared implementation, extends would be misleading 12

13 How represent Feline (and Why) ? A.Class B.Abstract Class C.Interface D.Extends Abstract class allows reusing some common implementation among Felines, and yet cannot be new’d (instantiated). Interface is a reasonable answer, too, as the sharing might not be too great. 13 Mammal FelineCanine Tiger House Cat

14 A Few Things to Remember  Avoid subclassing (extends)  Use when you have a real type hierarchy  And when you are lazy and want to share method implementations  But rare that non-leaf classes (like Mammal ) can be instantiated ( new ’d)  Subclassing abstract superclass is better  Captures “is-a” relationship of real type hierarchy  Purpose is still to borrow method implementations  But asserts that non-leaf class can’t be new ’d  Interfaces are the bomb  The most flexible  When you have multiple supertypes, or  When the subclasses are just implementation alternatives 14

15 Interfaces are Central to Java  Java Collections Framework  Interface Collection  methods like add(Object) & contains(Object)  interface List extends Collection … interface Set extends Collection … …  Wherever Collection variable appears, allows for a a ListArray or HashSet, etc.  Requires no particular implementation  Super-flexible code 15

16 Strategy Pattern Composition + Delegation + Interfaces 16

17 Car Description: What’s Wrong? abstract class CarDesc { Color paintColor(); int wheelbase(); … int tireSize(); boolean tirePerf(); String tireSeason(); /* should be enum */ } abstract class SmallCar extends CarDesc { … } class KiaSoul extends SmallCar { … int tireSize() { return 165; } boolean tirePerf() { return false; } String tireSeason() { return “All”; } A.CarDesc and maybe SmallCar should be an interface B.All these classes should “implement” a Tire interface C.KiaSoul should have a Tire field As implemented, KiaSoul only allows one set of values for tire behavior. By adding a Tire field and delegating to its function, then all sorts of tires will be possible. (See next slide.) “A” is an OK answer, but it’s not nearly as big a deal as the inflexibility of the tire methods. 17

18 “Strategy Pattern” Design abstract class CarDesc { … } abstract class SmallCar extends CarDesc { … } class KiaSoul extends SmallCar { Tire tires; … int tireSize() { return tires.size(); } boolean tirePerf() { return tires.perf(); } String tireSeason() { return tires.season(); }  KiaSoul has Tires  Delegates tire method impls to Tire  Tire impl is reusable in other settings  Can change at runtime: 18 composes Tire (“has-a”) delegates to Tire (easy!) mySoul.changeTires(new DunlopSP());

19 “Strategy Pattern” Design abstract class CarDesc { … } abstract class SmallCar extends CarDesc { … } class KiaSoul extends SmallCar { Tire tires; … int tireSize() { return tires.size(); } boolean tirePerf() { return tires.perf(); } String tireSeason() { return tires.season(); }  KiaSoul has Tires  Delegates tire method impls to Tire  Tire impl is reusable in other settings  Can change at runtime: Tire should be a: A.Class B.Abstract class C.Interface Why? We want to leave KiaSoul open to having all kinds of tires, and an interface is most flexible. An abstract class is OK, too, if you think there is a Tire type hierarchy with significant shared implementation. Tire should be a: A.Class B.Abstract class C.Interface Why? We want to leave KiaSoul open to having all kinds of tires, and an interface is most flexible. An abstract class is OK, too, if you think there is a Tire type hierarchy with significant shared implementation. 19 composes Tire (“has-a”) delegates to Tire (easy!) mySoul.changeTires(new DunlopSP());

20 “Strategy Pattern” Design abstract class CarDesc { … } abstract class SmallCar extends CarDesc { … } class KiaSoul extends SmallCar { Tire tires; … int tireSize() { return tires.size(); } boolean tirePerf() { return tires.perf(); } String tireSeason() { return tires.season(); } 20 > _____Tire_____ int size() bool perf() String season() _MichelinPilot_ … _DunlopSP_ … … _____KiaSoul_____ Tire tires_________ int tireSize() bool tirePerf() String tireSeason() I’m going to disagree strongly with the prior semester on this one. MichelinPilot and DunlopSP should be subclasses of Tire. Tire should not be an interface. The “is a “ relationship clearly holds and “acts like” is clearly too weak. Just because methods aren’t shared right at this second, doesn’t mean that they won’t be later. Design needs to be principled, not fit the moment. We shouldn’t put to an interface, just because the present requirements require no methods. We certainly can envision plenty. We’ll make a mess if we later need to add roll(), “loseAir()”, “heatUp()”, etc, methods, which would be implanted the same across all tires, and Tire is an interface not a base class.

21 Widely Used for Algorithm Alternatives 21

22 Take-Aways  Start thinking about objects  Then think about types  Then “is a” vs “has a”  Then, consider the hierarchy  Are behaviors re-implemented because they don’t apply to all peer sub- types?  Are behaviors appearing where they shouldn’t, or doing things they shouldn’t, by inheritance?  Fix by overriding, if necessary  Better idea: Can the behaviors be moved down? An intermediary added?  Would pure abstract base classes be better served by interfaces [Java]?  Same behaviors, but not a common implementation  Behavior exhibited by other classes to which neither “as a” nor “is a” apply (just plain different classes)  Consider “is a” vs “has a” and then, as a refinement, “is a” versus “act like a” 22

23 That mysterious “Tracker” object 23 class Friend { Location location(); boolean online(); Bitmap image(); } class Friends implements Iterable { Friends online(); Friends locationKnown(); // −> online? } Given I am logged in And my location is known When my friends are online And my friends’ location is known And my friends are near me Then I see them on the map  Basic idea is an intermediary whose Single Responsibility is drawing my friends on the map class NearbyFriendsTracker { private Friends friends; private GoogleMap map; NearbyFriendsTracker(GMap map, Friends friends); void showNearbyFriends(); }  Single responsibility : drawing friends on map!  Don’t have to bunch of “extra” methods  Very similar, despite SRP  Still trying to make code sounds like specification 4.Right things call right messages

24 UML Diagram: Middleman Design 24 _NearbyFriendsTracker_ - GoogleMap map - Friends friends −−−−−−−−−−−−−−−−− + showNearbyFriends() _________Friends_________ - List friends −−−−−−−−−−−−−−−−− + Friends online() + Friends locationKnown() _GoogleMap_ … _________Friend_________ + boolean online() + Location location() + Bitmap image() * _Iterable_ … Our ten-cent OO Design theory did not account for this object. But OO Design does. Nearby is a relationship Does not “belong” to Friends or GoogleMap Active relationships must be represented by a separate object like NearbyFriendsTracker Passive relationships can be represented by a separate object or a field/method Nearby is a relationship Does not “belong” to Friends or GoogleMap Active relationships must be represented by a separate object like NearbyFriendsTracker Passive relationships can be represented by a separate object or a field/method

25 Theory of Object-Oriented, IV 25 _NearbyFriendsTracker_ - GoogleMap map - Friends friends −−−−−−−−−−−−−−−−− + showNearbyFriends() _________Friends_________ - List friends −−−−−−−−−−−−−−−−− + Friends online() + Friends locationKnown() _GoogleMap_ … _________Friend_________ + boolean online() + Location location() + Bitmap image() * _Iterable_ … 1.Identify the “things” 2.Identify the messages 3.Identify the relationships 4.Assemble “things” & messages into classes 5.Encode relationships into classes/methods that point at “thing” classes 1.Identify the “things” 2.Identify the messages 3.Identify the relationships 4.Assemble “things” & messages into classes 5.Encode relationships into classes/methods that point at “thing” classes

26 Design Patterns Now experience doesn’t have to be a cruel teacher 26 Gang of Four

27 Rework the Design (UML OK) class Operation { public int execute (int a, int b) { return a + b; } class Multiply extends Operation { public int execute (int a, int b) { return fa * fb; } } class Subtract extends Operation {…} class Divide extends Operation {…} 27 ___Operation___ execute(int,int) ____Multiply____ execute(int,int) _____Divide____ execute(int,int) … Apply the Strategy Pattern

28 What’s the problem with this design? class Operation { public void execute (int a, int b) { return a + b; } class Multiply extends Operation { public void execute (int a, int b) { return fa * fb; } } class Subtract extends Operation {…} class Divide extends Operation {…} 28 ___Operation___ execute(int,int) ____Multiply____ execute(int,int) _____Divide____ execute(int,int) … A.Nothing, this is a good design B.Use of subclassing C.Subclassing is OK, but shouldn’t override methods D.If I add a new method to Operation, may have to modify all the subclasses

29 It’s called extends!  If you’re not extending the class, bad sign  Occasional override OK if you’re also extending  But subclassing is not for alternatives  For representing an actual type hierarchy  Multiply and Divide are just alternatives, and Operation is placeholder: interface! 29 Mammal FelineCanine Tiger House Cat

30 Strategy Design Interface OperationStrategy { public int execute (int a, int b); } class MultiplyStrategy implements OperationStrategy { public int execute (int a, int b) { return fa * fb; } } … 30 > _OperationStrategy_ execute(int,int) _MultiplyStrategy_ execute(int,int) _DivideStrategy_ execute(int,int) … class Calculate { private OperationStrategy opStrategy; public Calculate (OperationStrategy os) { opStrategy = os; } public int execute (int a, int b) { return opStrategy.execute(a, b); } } ___________Calculate___________ _ Operation Strategy_opStrategy _ execute(int,int) Calculate composes OperationStrategy (“has-a”) Calculate delegates to OperationStrategy Different implementations of same idea, not subclasses of general idea

31 What’s cool about strategy: runtime change class Calculate { private OperationStrategy opStrategy; public Calculate (Operation Strategy os) { opStrategy = os; } public setStrategy (Operation Strategy os) { opStrategy = os; } public int execute (int a, int b) { return opStrategy.execute(a, b); } } public static void main(…) { Calculate calculator = new Calculator( new MultiplicationStrategy()); System.out.println( calculator.execute(3,4)); /* 12 */ calculator.setStrategy( new AdditionStrategy()); System.out.println( calculator.execute(3,4)); /* 7 */ 31

32 Good-Enough Design Isn’t…Enough  Too slow, focused on a single object at a time  Experience can help us take big, fast leaps  But experience takes years to acquire  Design Pattern method is a shared vocabulary of software design experience  Focused on making software change easier  Focused on object interactions or relationships  Reduce “coupling”  Two things apart that have to change together  Two things together one has to change, other not 32

33 Design Pattern A template for how to solve a problem that can be used in many different situations (wikipedia)  Each pattern solves a different design problem  Ideally applied only when needed  Anticipated from experience  Refactoring (typically from “problem” code to solution code)  If it ain’t broke, don’t fix it  Use of design patterns adds complexity (and takes precious time!)  Cost vs. benefit 33

34 Agile and Always Runnable  If your app is running, you can confidently develop, test, debug, and demo  If it doesn’t run after adding new story, no fear  Roll back, debug new code, etc.  Failed tests, new bugs are due to new story  Narrows search, code still familiar  Can demo your new story right away  Self, teammates, customer 34

35 Always Runnable: How  User story is a “story” about a new thing that the user can do with app  So it should be demo-able, system testable, etc.  Keep stories small  But tendency is to make them too big  Write a system test or two (or script them)  Make part of your “continuous integration”  Don’t check in until system tests run 35

36 Always Runnable: Exercise “The basic idea is that you can see you and all your instant-messaging buddies on a map, allowing you to message a nearby friend (say, to meet up at a local café).  Let’s come up with a first “minimal” application (via User Story)  Then a few extensions (more User Stories) 36

37 Minimal myCity A. User can launch the application B. User can view a localized map C. User can view themselves on a localized map D. See yourself on the map, and send a message to yourself E.Create the chat and add one friend 37


Download ppt "Advanced OOD and the Strategy Pattern 1. In our last episode… (It was all about Object-Oriented Design) 2."

Similar presentations


Ads by Google