CSC 335 ObjectOriented Programming and Design PatternOriented Design
CSC 335: Object-Oriented Programming and Design Pattern-Oriented Design Review Design Patterns and UML by Rick Mercer based on the Go. F book and Design Patterns Explained A New Perspective on Object-Oriented Design Alan Shalloway, James R. Trott Addison Wesley ISBN 0 -201 -71594 -5 1
Using Patterns to Design w There are 23 Object-Oriented design patterns cataloged in the Go. F book—we’ve considered these ¾ Iterator, Observer, Strategy, Singleton, Command, Composite, Factory, Decorator, Flyweight, Façade, Proxy, State w We'll use some patterns to help design a system ¾ ¾ The new case study is in electronic retailing over the internet (An Ecommerce system, one where you buy stuff) Several design decisions will be aided by knowledge of existing design patterns · at a fairly high level of abstraction 2
Plan too much, plan ahead, or don’t plan at all? w Development of software systems can suffer from analysis paralysis ¾ attempt to consider all possible future changes w At other times developers jump to code too quickly ¾ there is tremendous pressure to deliver w Life’s three certainties for software developers ¾ Death, Taxes, and Changes in Requirements w There is a middle ground for planning for change 3
How will change occur w First, anticipate that changes will occur w Consider where they will change, rather than the exact nature of the changes w These issues will come up in the ECommerce case study 4
What is variable in the design? w Consider what is variable in your design ¾ Instead of focusing on what might force a change to your design · · Consider what might change Encapsulate the concept that varies – this is a theme of many design patterns w Hopefully there are long term benefits without a lot of extra work up front 5
Case study will use four OO Design Patterns w These design patterns help make for good design Strategy ¾ Singleton ¾ Decorator ¾ Observer ¾ 6
An Ecommerce System w There is a Task. Controller object that handles sales requests over the internet ¾ Example of the Mediator design pattern: defines an object that encapsulates how a set of objects interact · Often our listeners are Mediators (and controllers and command object) w When the sales order is requested, the controller delegates to a Sales. Order object 7
Assign Responsibilities w Sales. Order responsibilities: Allow users to make an order using GUI input ¾ Process the order ¾ Print a sales receipt ¾ 8
Changing Requirements w Start charging taxes on order from customers w need to add rules for taxation, but how? ¾ ¾ modify existing Sales. Order to handle U. S. taxes extend the existing Sales. Order object and modify the tax rules so it applies to the new country · This is an inheritance solution 9
Subclassing Solution Task. Controller Sales. Order Sales. Ticket. Printer +calc. Tax(): double US Tax Rules Canadian. Sales. Order +calc. Tax(): double 10
Favor Composition Over Inheritance w Design pattern theme of composition over inheritance is ignored in previous design w Here is a different approach ¾ ¾ consider what is variable in the design encapsulate the concept the varies w Accept the fact that tax rules vary country to country and state to state and county to county, and sometimes city to city (like in Arizona) and they do change! 11
Summary of Alternate Designs w Could use an abstract class with an abstract double calc. Tax() and many classes in a hierarchy w Or design an interface to be implemented by different classes using different algorithms ¾ Then have Sales. Order contain a reference to the correct object (favor composition over inheritance) public interface Tax. Calculator { // A Salable object knows price and how it is taxed public double tax. Amount(Salable item. Sold, double how. Many); } 12
A Better Design with Strategy 13
Why does Strategy make this design better? w Better Cohesion (hangs together) ¾ sales tax details are in its own class w Easy to add tax rules from different countries w Easier to shift responsibilities ¾ In the first design where Canadian. Sales. Order extends USSales. Order, only Task. Controller is able to determine which type of sales order to use · ¾ program to an interface, rather than an implementation With Strategy, either Task. Controller or Sales. Order could set the Tax. Calculator 14
Determine What Varies w What Varies? ¾ The business rules for taxation w Current design handles variations at least as well as the design with inheritance w Strategy can handle future variations better w A family of tax calculation algorithms have been encapsulated as objects, they are interchangeable, ¾ This is the Strategy pattern applied 15
Using the Strategy Pattern w What happens when English. Taxer is added ¾ In England, old-age pensioners are not required to pay taxes on sales items w How can this be handled? 1) Pass age of the Customer to Tax. Calculator object 2) Be more general and pass a Customer object 3) Be even more general and pass a reference to the Sales. Order object (this) to the Tax. Calculator and let that English. Strategy object ask Sales. Order for customer age (post some html to the client) 16
Is this change bad? w To handle this new requirement, Sales. Order and Tax. Calculator have to be modified ¾ ¾ But the change is small and certainly doable Not likely to cause a new problem w If a Strategy needs more information, pass the information to the object as an argument ¾ Some objects may ignore the extra parameter w Strategy can be applied anywhere you hear this ¾ "At different times, different rules apply" 17
Singleton Pattern w Singleton Ensure a class only has one instance and provide a global point of access to it w The singleton pattern works by having a special method that is used to instantiate the object ¾ ¾ ¾ when called, the method checks to see if the object has already been instantiated it returns the singleton if instantiated or constructs a new one if this is the first call to get the instance to guarantee this, have a private constructor 18
Using Singleton w Tax. Calculators are currently encapsulated as Strategy objects ¾ How many USTaxer objects are required in this system? How many Canadian. Taxers? w Forces: ¾ ¾ ¾ The same object is being used over and over again More efficient to avoid instantiating them and throwing them away again and again Doing all at once could be slow to start up · Could instantiate these objects as needed 19
Only want one when needed w Don’t need more than one instance of each Tax. Calculator class w Solution: ¾ ¾ Let Strategy objects handle the instantiation Let there be only one instance Don’t concern the Sales. Order object with this detail In other words, use the Singleton design pattern 20
USTaxer is now a Singleton public class USTaxer implements Tax. Calculator { private static USTaxer instance; // Only one private static double tax. Rate; private USTaxer() { tax. Rate = 0. 06; // greatly simplified } // This is thread safe public static synchronized USTaxer get. Instance() { if (instance == null) instance = new USTaxer(); return instance; } } public double tax. Amount(Salable item, double quan) { return 0; // TODO: Implement tax algorithm } 21
dependency aggregation (Salable is one part of Sales. Order) implements 22
Other Patterns applied w In the Ecommerce system, we will now ¾ ¾ “Decorate” a Sales. Ticket and “Observe” a Customer 23
Decorate Sales. Ticket. Printer w Assume the Sales. Ticket. Printer currently creates an html sales receipt Airline Ticket w New Requirement: Add header with company name, add footer that is an advertisement, during the holidays add holiday relevant header(s) and footer(s), we’re not sure how many w One solution ¾ Place control in Sales. Ticket. Printer · Then you need flags to control what header(s) get printed 24
One Solution w This works well if there are few header and footer options or perhaps just add a few private helper methods underline indicates static methods 25
Need to employ a Design Pattern? w If there are many types of headers and footers, with only one being printed each time, use Strategy w If there will be more than one header and footer, and/or the ordering changes, and/or the number of combinations grows, ¾ use the Decorator design pattern to chain together the desired functionality in the correct order needed 26
Decorator Again w Decorator summary repeated Attach additional Responsibilities to an object dynamically w Go. F book states: Decorators provide a flexible alternative to subclassing for functionality w Start chain with decorators, end with original object Decorator 1 Decorator 2 Concrete Component Example: keyboard = new Buffered. Reader( new Input. Stream. Reader( System. in)); 27
28
A Simple Sales. Ticket abstract class Component { abstract public void print. Ticket(); } // Instances of this class are sales tickets // that may be decorated class Sales. Ticket extends Component { @Override public void print. Ticket() { // Hard coded here, but simpler than // adding a new Customer class. . . System. out. println("Customer: Kim"); System. out. println("The sales ticket itself"); System. out. println("Total: $123. 45"); } } 29
Ticket. Decorator abstract class Ticket. Decorator extends Component { private Component my. Component; public Ticket. Decorator() { my. Component = null; } public Ticket. Decorator(Component c) { my. Component = c; } } @Override public void print. Ticket() { if (my. Component != null) my. Component. print. Ticket(); } 30
A Header Decorator class Header. Decorator 1 extends Ticket. Decorator { public Header. Decorator 1(Component c) { super(c); } @Override public void print. Ticket() { this. print. Header(); super. print. Ticket(); } } public void print. Header() { System. out. println("@@ Header One @@"); } 31
A Footer Decorator class Footer. Decorator 1 extends Ticket. Decorator { public Footer. Decorator 1(Component c) { super(c); } @Override public void print. Ticket() { super. print. Ticket(); this. print. Footer(); } } public void print. Footer() { System. out. println("%% FOOTER one %%"); } 32
A Client public class Client { public static void main(String[] args) { Component my. ST = Configuration. get. Sales. Ticket(); my. ST. print. Ticket(); } } 33
Simple Configuration // This method determines how to decorate Sales. Ticket class Configuration { } public static Component get. Sales. Ticket() { // Return a decorated Sales. Ticket return new Header. Decorator 1( new Header. Decorator 2( new Footer. Decorator 1( new Sales. Ticket() ) ) ; } 34
Output with Current Configuration Output: @@ Header One @@ >> Header Two << Customer: Bob The sales ticket itself Total: $123. 45 %% FOOTER one %% ## FOOTER two ## 35
The system on 2 slides Sales. Order delegates to Component to print ticket 36
37
Observe Customer w New Requirements: Send an email to a new customer and verify the customer's address with the post office w If this was it, hard code Customer behavior when being added to data base 38
Or Use Observer w With additional behaviors (such as send advertisements via snail mail), there may be a changing list of objects that need notification that a new customer is being added w These objects will have different interfaces ¾ Send. Email, Send. Coupons. Via. Snail. Mail, Sell. Private. Information. To. Telemarketers, . . w Next up: change two objects into "Observers" 39
Observer w Have Customer extend Observable w Have all of the objects that need notification implement Observer (all have the update method) w Have some configurer add the correct observers to the Customer object with add. Observers w Have the add. Customer method send the message notify. Observers 40
Design with Observer gather. Coupons() 41
- Slides: 41