Design Patterns Slides adapted from various sources Slide 1 Outline • • • • • Introduction An example: the Observer pattern History and definition of design patterns Design pattern names and categories Other Patterns: Facade, Singleton, Composite, Adapter, Bridge • Pattern description Templates • Summary & Benefits Slide 2 Software Design – bridging the gap between requirements & Implementation Software Design Requirements Analysis Implementation Systems Engineering Evolution Deployment Testing • What is software design? – Expressing a solution to a problem in programming language independent terms – creating a blueprint for implementation. Slide 3 3 Design challenges • Designing software for reuse is hard; one must find: – a good problem decomposition, and the right software abstractions – a design with flexibility, modularity and elegance • Designs often emerge from an iterative process (trials and many errors) • Successful designs do exist – two designs are almost never identical – they exhibit some recurring characteristics • The engineering perspective: can designs be described, codified or standardized? – this would short circuit the trial and error phase – produce "better" software faster Slide 4 Design Rules for Architecting system characteristics Performance Localize critical operations and minimize communications. Use large rather than fine-grain components. Security Use a layered architecture with critical assets in the inner layers. Safety Localize safety-critical features in a small number of sub-systems. Availability Include redundant components and mechanisms for fault tolerance. Maintainability Use fine-grain, replaceable components. Slide 5 5 Design Rules for General System Design Coupling Design and architect software so as to minimize the coupling of software components. Cohesion Design and architect software so as to maximize the cohesion of software components. Low coupling – high cohesion. Slide 6 6 Design challenges • The engineering perspective: –Can designs be described, codified and standardized? –What would such a standard look like? –Standardization would short circuit the trial and error phase of design and potentially produce better software. Slide 7 Standardizing Design Slide 888 A Scenario Views Relative Percentages A B C D X 15 35 35 15 Y 10 40 30 20 Z 10 40 30 20 Change notification Requests, modifications A D B C A B A=10% B=40% C=30% D=20% Data C D Slide 9 A Scenario Views Relative Percentages A B C D X 15 35 35 15 Y 10 40 30 20 Z 10 40 30 20 Change notification Requests, modifications A D B C A B A B C D C D 10 40 30 20 Application Data • Rules/Principles – Separate presentational aspects from the data, i.e. separate views and data. – Change in one view automatically reflected in other views. Also, change in the application data is reflected in all views. – Define one-to-many dependency amongst objects so that when one object changes its state, all its dependents are notified. – Support reuse of classes defining application data and presentation. Slide 10 Is this a pattern of design? Observer Relative Percentages A B C D X 15 35 35 15 Y 10 40 30 20 Z 10 40 30 20 A D B C A B C D A=10% B=40% C=30% Change notification D=20% Requests, modifications Data, Model or Subject Slide 11 The Model-view-controller architecture Data or Subject Model Functionality change notifies Controller query change View User Interface or Observer • Separates the application object (model) from • The way it is presented to the user (view), from • The way in which the user controls it (controller). 12 Slide 12 What other patterns have you seen in this class? Slide 13 Architectural Patterns to Date Client invocation res ult A K Server invocation Server res ult T Client Key: Process : Computer: Slide 14 The seven layers of architecture* OO architecture Global architecture Enterprise architecture ORB Subsystem System architecture Application architecture Macro-architecture Frameworks Design patterns Micro-architecture Objects OO programming Slide 15 * Mowbray and Malveau Goals of Design Standardization • Codify good design – Distil and disseminate experience – Aid to novices and experts alike – Abstract how to think about design © E. Gamma, R. Helm, R. Johnson, J. Vlissides and Addison-Wesley • Give design structures explicit names – Common vocabulary – Reduced complexity – Greater expressiveness • Capture and preserve design information – Articulate design decisions succinctly – Improve documentation • Enhance important non-functional properties – – – – Changeability Reliability Testability Etc. Slide 16 How design patterns arise Problem Forces Solution Benefits Consequences Related Patterns Slide 17 Definition & Purpose • A recurring solution to a common software problem in a context. – A design pattern captures design expertise –patterns are not created from thin air, but abstracted from existing design examples – Using design patterns is reuse of design expertise – Studying design patterns is a way of studying how the “experts” do design – Design patterns provide a vocabulary for talking about design Slide 18 Is this a design pattern? Observer Relative Percentages A B C D X 15 35 35 15 Y 10 40 30 20 Z 10 40 30 20 A D B C A B C D A=10% B=40% C=30% Change notification D=20% Requests, modifications Data, Model or Subject Slide 19 Observer Design Pattern observers Subject Observer attach (Observer) detach (Observer) Notify () Update() For all x in observers{ x Update(); } Concrete Observer Concrete Subject GetState() SetState() subjectState subject Update() observerState observerState= subject getState(); Slide 20 Class collaboration in Observer :ConcreteSubject a:ConcreteObserver b:ConcreteObserver SetState() Notify() Update() GetState() Update() GetState() Slide 21 Code Example: An Observer public interface IObserver { void update(String state); } public class Observer1 implements IObserver { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public void update(String state) { setState(state); System.out.println("Observer1 has received update signal with new state: " + getState()); } } Slide 22 Code Example: A Second Observer public class Observer2 implements IObserver { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public void update(String state) { setState(state); System.out.println("Observer2 has received update signal with new state: " + getState()); } } Slide 23 Code Example: The Subject public class LogSubject { private List<IObserver> observerList = new ArrayList<IObserver>(); private String state; public String getState() { return state; } public void attach(IObserver observer) { observerList.add(observer); } public void detach(IObserver observer) { observerList.remove(observer); } public void setState(String state) { this.state = state; notify(); } private void notify() { for (IObserver item: observerList) { item.update(getState()); } }} Slide 24 Code Example: The main Program public class Client { public static void main(String[] args) { LogSubject subject = new LogSubject(); IObserver ob = new Observer(); IObserver ob1 = new Observer1(); IObserver ob2 = new Observer2(); subject.attach(ob); subject.attach(ob1); subject.attach(ob2); subject.setState("state1"); subject.setState("state2"); subject.detach(ob1); subject.setState("state3"); } } Slide 25 Code Example 2 Slide 26 Observer Pattern: Observer code class Subject; class observer { public: Abstract class defining the Observer interface. virtual ~observer; virtual void Update (Subject* theChangedSubject)=0; protected: observer (); }; Note the support for multiple subjects. CS 406: Design Patterns Slide 27 27 Observer Pattern: Subject Code [1] class Subject { Abstract class defining the Subject interface. public: virtual ~Subject; virtual void Attach (observer*); virtual void Detach (observer*) ; virtual void Notify(); protected: Subject (); private: List <Observer*> *_observers; }; CS 406: Design Patterns Slide 28 28 Observer Pattern: Subject Code [2] void Subject :: Attach (Observer* o){ _observers -> Append(o); } void Subject :: Detach (Observer* o){ _observers -> Remove(o); } void Subject :: Notify (){ ListIterator<Observer*> iter(_observers); for ( iter.First(); !iter.IsDone(); iter.Next()) { iter.CurrentItem() -> Update(this); } } CS 406: Design Patterns Slide 29 When to use the Observer Pattern? • When an abstraction has two aspects: one dependent on the other. Encapsulating these aspects in separate objects allows one to vary and reuse them independently. • When an update to one object requires changing others and the number of objects to be changed is not known. • When an object should be able to notify others without knowing who they are. Avoid tight coupling between objects. Slide 30 Observer Pattern: Benefits • Abstract coupling between subject and observer. Subject has no knowledge of concrete observer classes. • Support for broadcast communication. A subject need not specify the receivers; all interested objects receive the notification. • Unexpected updates: Observers need not be concerned about when updates are to occur. They are not concerned about each other’s presence. Slide 31 Slide3232 32 Observer Pattern History • Software context: – Most of the work originated in SmallTalk community. – SmallTalk programming language: • • • • • Object Oriented Meant for rapid prototyping Came with (what are known today as) IDE and API IDE elements were in SmallTalk! (Concrete) Precursor to modeling, frameworks and patterns! Slide 33 Patterns – MVC framework • SmallTalk’s user interface framework – Model - refers to data model – View – refers to external views or presentation of data. – Controller – refers to module relating reactions of view or presentation to changes in data. Slide 34 The Model-view-controller architecture Data or Subject Model Functionality change notifies Controller query change View User Interface or Observer • Separates the application object (model) from • The way it is presented to the user (view), from • The way in which the user controls it (controller). 35 Slide 35 Observer Pattern • Model – View paradigm can be generalized: – A view is an observer – A model is an subject that is observed. – The controller may be the communication between model and view or may be incorporated in the view or model. Slide 36 Pattern origins and history • Writings of architect Christopher Alexander (coined this use of the term "pattern" ca. 1977-1979) – A Pattern Language in 1977 (253 patterns) • Kent Beck and Ward Cunningham, Textronix, OOPSLA'87 (used Alexander's "pattern" ideas for Smalltalk GUI design) • Erich Gamma, Ph. D. thesis, 1988-1991 • Gamma, Helm, Johnson, Vlissides ("Gang of Four“ - GoF) Design Patterns: Elements of Reusable Object-Oriented Software, 1991-1994 • James Coplien, Advanced C++ Idioms book, 1989-1991 • PLoP Conferences and books, 1994-present: http://hillside.net/plop/2006/ • Buschmann, Meunier, Rohnert, Sommerland, Stal, Pattern -Oriented Software Architecture: A System of Patterns (“POSA book”) Slide 37 Definition • A recurring solution to a common software problem in a context. • Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice [Alexander]. • … the abstraction from a concrete form which keeps recurring in specific non-arbitrary contexts [Riehle]. • …both a thing and the instructions for making the thing [Coplien] • ...a literary format for capturing the wisdom and experience of expert designers, and communicating it to novices. Slide 38 Slide3939 39 Design pattern catalog - GoF Purpose Creational Structural Behavioral Class Factory Method Adapter Interperter Object Abstract Factory Builder Prototype Singleton Scope Adapter Bridge Composite Decorator Facade Flyweight Proxy Chain of Responsibility Command Iterator Mediator Momento Observer State Strategy Vistor •• Structural Creational patterns patterns • Behavioral – Concernspatterns how groups of objects are composed into larger structures – – – – – Abstracts the instantiation process Defines communication among objects in a given system Dynamically create objects so that they don’t have to be instantiated Provides directly. better control of flow in a complex application Help make a system independent of how objects are represented, created Slide 40 and composed. Types of software patterns • Design patterns (software design) [Buschmann-POSA] – architectural (systems design) – Susbsystem design (micro-architectures) [Gamma-GoF] • • • • Analysis patterns (recurring & reusable analysis models) [Flower] Organization patterns (structure of organizations/projects) Process patterns (software process design) Other patterns… Slide 41 Slide4242 42 Facade Pattern: Problem B A Client Classes C Need to communicate with s1 s5 s2 s4 s3 Subsystem classes Slide 43 Facade Pattern: Solution B A Client Classes C Facade S1 S5 S2 S4 S3 Subsystem classes Slide 44 Facade • Provide unified interface to interfaces within a subsystem • Shield clients from subsystem components • Promote weak coupling between client and subsystem components Client Facade Slide 45 Facade Pattern: Why and What? • Subsystems often get complex as they evolve. • Need to provide a simple interface to many, often small, classes. But not necessarily to ALL classes of the subsystem. • Facade provides a simple default view good enough for most clients. • Facade decouples a subsystem from its clients. • A facade can be a single entry point to each subsystem level. This allows layering. Slide 46 Facade Pattern: Benefits • Shields clients from subsystem classes; reduces the number of objects that clients deal with. – Clients do not have direct access to subsystem classes. • Promotes weak coupling between subsystem and its clients. • Helps in layering the system. Helps eliminate circular dependencies. Slide 47 Singleton Structure Singleton static uniqueInstance return uniqueinstance singletonData static Instance() SingletonOp() GetSingletonData() Slide 48 Composite • Construct part-whole hierarchy • Simplify client interface to leaves/composites • Easier to add new kinds of components Component Client 0..* Operation() Add(Component) Remove(Component) children Leaf Operation() Composite Operation() Add(Component) Remove(Component) For all c in children c.Operation(); Slide 49 Composite (2) • Example: figures in a structured graphics toolkit Controller View 0..* Figure paint() 0..* children translate() getBounds() LabelFigure BasicFigure CompositeFigure paint() paint() paint() addFigure(Figure)) removeFigure(Figure)) parent For all c in children c.paint(); Slide 50 Adapter pattern ClientInterface LegacyClass Request() ExistingRequest() Client adaptee Adapter Request() Slide 51 Adapter pattern target adaptee • • • • Delegation is used to bind an Adapter and an Adaptee Interface inheritance is use to specify the interface of the Adapter class. Target and Adaptee (usually called legacy system) pre-exist the Adapter. Target may be realized as an interface in Java. Slide 52 Using the Adapter Pattern interface IBank { public void deposit(double amount); public double withdraw(double amount); public void transfer(Account from, Account to, double amount); public double getBalance(); public Account getAccount(int accountNumber); } class BankClass implements IBank { //… } class StockClass implements IBank { //… } Original Environment BankClass b = new BankClass(); StockClass obj = new StockClass(); obj.deposit(b.withdraw(200)); obj.transfer(b.getAccount(), b.getAccount(), 400); Slide 53 Adapting to a new environment class BankClass implements IBank { //… } class StockClass implements IBank { //… } class BankClass implements IBank { //… } class StockClass implements IStock { //… } Original Environment New Environment Slide 54 Adapting to a new environment: will the old code work? interface IBank { public void deposit(double amount); public double withdraw(double amount); public void transfer(Account from, Account to, double amount); public double getBalance(); public Account getAccount(int accountNumber); } interface IStock { public boolean deposit(float amount); public void withdraw(double amount); public boolean transfer(Account from, Account to, Money m); BankClass b = new BankClass(); public double getBalance(); StockClass obj = new StockClass(); } obj.deposit(b.withdraw(200)); obj.transfer(b.getAccount(), b.getAccount(),Slide 400); 55 Will the old code work? class BankClass implements IBank { public static void main(String[] args) { BankClass b = new BankClass(); StockClass obj = new StockClass(); obj.deposit(b.withdraw(200)); BankClass b = new BankClass(); StockClass obj = new StockClass(); obj.deposit((float)b.withdraw(200)); } } So casting will do in this case. Slide 56 Will the old code work? class BankClass implements IBank { public static void main(String[] args) { but the Client code has to change… BankClass b = new BankClass(); StockClass obj = new StockClass(); obj.transfer(b.getAccount(12345), b.getAccount(45567), 400); public class StockClassWrapper implements IBank{ public void transfer(Account from, Account to, double amount) { } StockClass s = new StockClass(); s.transfer(from, to, new Money(amount)); } Create an Adapter class } } So casting will NOT do … Slide 57 Will the old code work? class BankClass implements IBank { public static void main(String[] args) { BankClass b = new BankClass(); StockClassWrapper obj = new StockClassWrapper(); obj.transfer(b.getAccount(12345), b.getAccount(45567), 400); public class StockClassWrapper implements IBank{ public void transfer(Account from, Account to, double amount) { } StockClass s = new StockClass(); s.transfer(from, to, new Money(amount)); } } } Slide 58 Will the old code work? class BankClass implements IBank { public static void main(String[] args) { Now the client class need not change … BankClass b = new BankClass(); StockClass obj = new StockClass(); obj.transfer(b.getAccount(12345), b.getAccount(45567), 400); public class StockClass implements IBank{ public void transfer(Account from, Account to, double amount) { } OldStockClass s = new OldStockClass(); s.transfer(from, to, new Money(amount)); } } } Slide 59 Adapter Pattern Summary • “Convert the interface of a class into another interface clients expect.” • The adapter pattern lets classes work together that couldn’t otherwise because of incompatible interfaces • Used to provide a new interface to existing legacy components (Interface engineering, reengineering). • Also known as a wrapper • Two adapter patterns: – Class adapter: • Uses multiple inheritance to adapt one interface to another – Object adapter: • Uses single inheritance and delegation Slide 60 Bridge Pattern • Use a bridge to “decouple an abstraction from its implementation so that the two can vary independently”. (From [Gamma et al 1995]) • Also know as a Handle/Body pattern. • Allows different implementations of an interface to be decided upon dynamically. • The bridge pattern is used to provide multiple implementations under the same interface. – Examples: Interface to a component that is incomplete, not yet known or unavailable during testing Slide 61 Bridge Pattern Client imp Abstra ct ion Impleme ntor Ope ra tion() OperationImp l() Imp ->Op erationIm p( ); Refi ned Ab straction 1 Refi ned Ab straction 2 Ope ra tion() Ope ra tion() Con crete Implementor A Con crete Implementor B Ope ra tionImp l() Ope ra tionImp l() Slide 62 Adapter vs Bridge • Similarities: – Both are used to hide the details of the underlying implementation. • Difference: – The adapter pattern is geared towards making unrelated components work together • Applied to systems after they’re designed (reengineering, interface engineering). – A bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently. • Engineering of an “extensible system” • New “beasts” can be added to the “object zoo”, even if these are not known at analysis or system design time. Slide 63 Slide6464 64 Pattern Description: GoF form Pattern name and classification Intent what does pattern do / when the solution works Also known as other known names of pattern (if any) Motivation the design problem / how class and object structures solve the problem Applicability situations where pattern can be applied Structure a graphical representation of classes in the pattern Participants the classes/objects participating and their responsibilities Collaborations of the participants to carry out responsibilities Slide 65 Pattern Description: GoF form Consequences trade-offs, concerns Implementation hints, techniques Sample code code fragment showing possible implementation Known uses patterns found in real systems Related patterns closely related patterns Slide 66 Pattern Description: Alexandrian form Name meaningful name Problem the statement of the problem Context a situation giving rise to a problem Forces a description of relevant forces and constraints Solution proven solution to the problem Examples sample applications of the pattern Resulting context (force resolution) the state of the system after pattern has been applied Slide 67 Pattern Description: Alexandrian form Rationale explanation of steps or rules in the pattern Related patterns static and dynamic relationship Known use occurrence of the pattern and its application within existing system Slide 68 69 • List six benefits of design pattern usage in software engineering. Slide 69 69 Slide7070 70 Benefits of using patterns • Patterns are a common design vocabulary – allows engineers to abstract a problem and talk about that abstraction in isolation from its implementation – embodies a culture; domain specific patterns increase design speed • Patterns capture design expertise and allow that expertise to be communicated – promotes design reuse and avoid mistakes • Improve documentation (less is needed) and understandability (patterns are described well once) • Using design patterns is reuse of design expertise • Studying design patterns is a way of studying how the “experts” do design • Patterns do not provide exact solutions, solve all design problems or only apply to OO systems. Slide 71 Patterns vs “Design” • Patterns are design – But: patterns transcend the “identify classes and associations” approach to design – Instead: learn to recognize patterns in the problem space and translate to the solution • Patterns can capture OO design principles within a specific domain • Patterns provide structure to “design” Slide 72 Patterns vs Frameworks • Patterns are lower-level than frameworks • Frameworks typically employ many patterns: – – – – Factory Strategy Composite Observer • Done well, patterns are the “plumbing” of a framework Slide 73 Patterns vs Architecture • Design Patterns (GoF) represent a lower level of system structure than “architecture” (cf: seven levels of A) • Patterns can be applied to architecture: – Mowbray and Malveau – Buschmann et al – Schmidt et al • Architectural patterns tend to be focussed on middleware. They are good at capturing: – Concurrency – Distribution – Synchronization Slide 74 More about patterns • A pattern describes a recurring software structure – is abstract from concrete design elements such as problem domain, programming language – identifies classes that play a role in the solution to a problem, describes their collaborations and responsibilities – lists implementation trade-offs – patterns are not code or designs; must be instantiated/applied • The software engineer is required to: – evaluate trade-offs and impact of using a pattern in the system at hand – Make design and implementation decision how best to apply the pattern, perhaps modify it slightly – Implement the pattern in code and combine it with other patterns Slide 75 76 • Something to ponder as you leave: – How can design patterns aid MDE? Slide 76 76 Online resources • Pattern FAQ • http://g.oswego.edu/dl/pd-FAQ/pd-FAQ.html • Basic patterns • http://exciton.cs.oberlin.edu/javaresources/DesignPatt erns/default.htm • Patterns home page • http://hillside.net/patterns/ Slide 77 Other resources • Design Patterns – Elements of Reusable Object-Oriented Software – Erich Gamma, et. Al, ISBN 0-201-63361-2 • Java Design Patterns – James W. Cooper, ISBN 0-201-48539-7 • Head First Design Patterns – Eric & Elisabeth Freeman (with Kathy Sierra & Bert Bates) – ISBN 0-596-00712-4 Slide 78 The End Qu es ti ons? ______________________ Devon M. Simmonds Computer Science Department University of North Carolina Wilmington _____________________________________________________________ Slide 79 79 An Example: http://en.wikipedia.org/wiki/Bridge_pattern import java.util.*; /** "Implementor" */ interface DrawingAPI { public void drawCircle(double x, double y, double radius);} /** "ConcreteImplementor" 1/2 */ class DrawingAPI1 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius); } } /** "ConcreteImplementor" 2/2 */ class DrawingAPI2 implements DrawingAPI { public void drawCircle(double x, double y, double radius) { System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius); } } Slide 80 An Example … /** "Abstraction" */ interface Shape { public void draw(); public void resizeByPercentage(double pct); } /** "Refined Abstraction" */ class CircleShape implements Shape { private double x, y, radius; private DrawingAPI drawingAPI; public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) { this.x = x; this.y = y; this.radius = radius; this.drawingAPI = drawingAPI; } public void draw() { drawingAPI.drawCircle(x, y, radius); } public void resizeByPercentage(double pct) { radius *= pct; } } Slide 81 An Example … /** "Client" */ class BridgePattern { public static void main(String[] args) { Shape[] shapes = new Shape[2]; shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1()); shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2()); for (Shape shape : shapes) { shape.resizeByPercentage(2.5); shape.draw(); } } } Slide 82 Observer design pattern: example 2 TextDisplay s tifi e o n BankStatementData notifies BarGraphDisplay no t ifie s PieChartDisplay Slide 83 Slide 84