An Introduction to Design Patterns Software Engineering 12th March 2004 Introduction • What are design patterns? • Two concrete examples: – Façade – Observer • Brief summary of remaining “Gang Of Four” patterns • Why are they useful? • Where to find out more 12th March 2004 Introduction to Design Patterns 2 1 What Are Design Patterns? • Patterns first described by Christopher Alexander in the 1960s in the context of buildings • “A pattern addresses a recurring design problem that arises in specific design situations and presents a solution to it.” (Buschmann et al., 1996) • “Design patterns are recurring solutions to design problems you see over and over.” (Alpert et al., 1998) • Hundreds of patterns exist at various levels of granularity e.g. organisation, architecture, analysis, programming idioms • Design patterns have been written about more than any other kind 12th March 2004 Introduction to Design Patterns 3 Mastering Chess • First learn rules and physical requirements – e.g. names of pieces, legal moves, chessboard layout etc. • Then learn principles – e.g. relative value of pieces, strategic value of centre squares etc. • Finally study the games of masters – understand the patterns, learn them and use them repeatedly where appropriate 12th March 2004 Introduction to Design Patterns 4 2 Mastering Software Design • First learn rules and physical requirements – e.g. algorithms, data structures, programming languages etc. • Then learn principles – e.g. modular programming, object-oriented programming etc. • Finally study the designs of masters – understand the patterns, learn them and use them repeatedly where appropriate 12th March 2004 Introduction to Design Patterns 5 Elements of a Design Pattern • Name – A title that conveys the essence of the pattern succinctly • Problem – A statement of the problem that describes the pattern’s intent • Solution – The elements that make up the design: relationships, responsibilities and collaborations • Consequences – The results and trade-offs of applying the pattern 12th March 2004 Introduction to Design Patterns 6 3 Façade – Problems Addressed • During development, classes are added to a subsystem (or API) as new functionality is needed • This leads to an increase in the number of classes the subsystem client has to use and know about • This causes two problems: – The client code can get very complex – The client and the API are tightly coupled • JDBC is a good example of this complexity: – Cumbersome to use: Connection, DatabaseMetaData, Statement, ResultSet, ResultSetMetaData classes 12th March 2004 Introduction to Design Patterns 7 Façade – Overview • Provides a unified interface to a set of classes in a subsystem and makes the subsystem easier to use • Decouples subsystem and its clients: – makes client code simpler – means that changes in subsystem affect client less • Reduces complexity by minimising communication between subsystems • Cooper shows how a Façade could be used to make JDBC simpler 12th March 2004 Introduction to Design Patterns 8 4 Façade – Structure “Before” Client classes Subsystem classes 12th March 2004 Introduction to Design Patterns 9 Façade – Structure “After” Client classes Facade Subsystem classes 12th March 2004 Introduction to Design Patterns 10 5 Façade – Mechanic Example Before Façade After Façade CarOwner CarOwner Mechanic service() Engine Brakes Engine Brakes addOil() changeFluid() addOil() changeFluid() Tyres Tyres pump() pump() 12th March 2004 Introduction to Design Patterns 11 Façade – Compiler Example Compiler compile() Stream Scanner Token Parser Symbol BytecodeStream ProgramNodeBuilder CodeGenerator ProgramNode StatementNode ExpressionNode StackMachineCodeGenerator 12th March 2004 RISCCodeGenerator Introduction to Design Patterns VariableNode 12 6 Compiler – Subsystem Classes • Many classes involved in the compiler e.g.: class Scanner { private Object inputStream; public Scanner (Object stream) { inputStream = stream; } public Token scan() { return new Token(); } } class Token { int type; } 12th March 2004 etc... Introduction to Design Patterns 13 Compiler – Façade Class class Compiler { public OutputStream compile(InputStream inputStream) { Scanner scanner = new Scanner(inputStream); ProgramNodeBuilder builder = new ProgramNodeBuilder(); Parser parser = new Parser(); RISCCodeGenerator generator = new RISCCodeGenerator(); ExpressionNode parseTree = new ExpressionNode(); parser.parse(scanner, builder); parseTree.traverse(generator); return generator.getOutputStream(); } } 12th March 2004 Introduction to Design Patterns 14 7 Compiler – Client • Client only uses compiler class... Compiler comp = new Compiler(); OutputStream os = comp.compile(input); ...rather than all subsystem classes: Scanner = new Scanner(input); ProgramNodeBuilder builder = new ProgramNodeBuilder(); Parser parser = new Parser(); etc... 12th March 2004 Introduction to Design Patterns 15 Façade – Consequences • Shields clients from subsystem components and makes subsystem easier to use • Promotes weak coupling between subsystem and its clients 12th March 2004 Introduction to Design Patterns 16 8 Observer – Problems Addressed • Frequently in programs, a number of objects need to know about a single object and must be told when it changes • Often the case in GUI programs e.g. share prices shown as a list and a graph • There are several problems we face: – Querying the object manually all the time to look for changes is inefficient – If the changing object has hard-coded notifications to the list and graph, we have to change the code each time we want a new object to be notified – inflexible and tightly coupled – Hard-coded notifications mean the the changing object has to know the class of each object it is notifying – again tight coupling and “spaghetti” code 12th March 2004 Introduction to Design Patterns 17 Observer – Overview • Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated • Maintains consistency between related objects but without enforcing tight coupling – Observers can add themselves dynamically to the Subject – Subject doesn’t care about details of Observers • Use it when: – a change to one object requires changes to others but you don’t know how many objects need to be changed – an object should be able to notify other objects without making assumptions about who they are • Used throughout Swing e.g. ActionListener, TableModel 12th March 2004 Introduction to Design Patterns 18 9 Observer – JButton Example AbstractButton fireActionPerformed() addActionListener(ActionListener a) listeners * <<interface>> ActionListener actionPerformed(Event e) implements JButton event source 12th March 2004 MyClass actionPerformed(Event e) Introduction to Design Patterns 19 Observer – Structure * observers Subject attach(Observer) detach(Observer) notify() <<interface>> Observer update() for all o in observers { o.update() } implements observerState = subject.getState() subject ConcreteSubject setState() getState() subjectState 12th March 2004 ConcreteObserver update() observerState Introduction to Design Patterns 20 10 Observer – Noticeboard Example Observable observers notifyObservers() deleteObserver(Observer o) addObserver(Observer o) * <<interface>> Observer update (Observable o, Object arg) implements implements Lecturer update (Observable o, Object arg) Noticeboard subject Student update (Observable o, Object arg) newMessage(String msg) getNewestMessage() newestMessage 12th March 2004 subject Introduction to Design Patterns 21 Noticeboard – Subject/Observable Class class Noticeboard extends Observable { private String newestMessage; public void newMessage(String msg) { this.newestMessage = msg; notifyObservers(); } public String getNewestMessage() { return newestMessage; } } 12th March 2004 Introduction to Design Patterns 22 11 Noticeboard – Concrete Observers class Lecturer implements Observer { public void update(Observable obs, Object arg) { Noticeboard nb = (Noticeboard) obs; System.out.println(“Lecturer has been told about new message: " + nb.getNewestMessage()); } // Other Lecturer-specific methods... } class Student implements Observer { public void update(Observable obs, Object arg) { Noticeboard nb = (Noticeboard) obs; System.out.println(“Student has been told about new message: " + nb.getNewestMessage()); } // Other Student-specific methods... } 12th March 2004 Introduction to Design Patterns 23 Noticeboard – Main Program and Output public class NoticeboardTest { public static void main(String[] args) { Noticeboard nb = new Noticeboard(); Lecturer lect = new Lecturer(); Student stu = new Student(); nb.addObserver(lect); nb.addObserver(stu); nb.newMessage(“First Message”); nb.newMessage(“Second Message”); } } Lecturer has been told about new message: First Message Student has been told about new message: First Message Lecturer has been told about new message: Second Message Student has been told about new message: Second Message 12th March 2004 Introduction to Design Patterns 24 12 Noticeboard – Sequence Diagram :NoticeboardTest nb:Noticeboard lect:Lecturer stu:Student newMessage(“First Message”) notifyObservers() update(nb, null) getNewestMessage() update(nb, null) getNewestMessage() 12th March 2004 Introduction to Design Patterns 25 Observer – Consequences • Abstract and minimal coupling between Subject and Observer • Support for broadcast communication • Observer independence can cause unexpected behaviour 12th March 2004 Introduction to Design Patterns 26 13 Design Pattern Types • Creational Patterns – These deal with creating, initialising and configuring classes and objects • Structural Patterns – These deal with decoupling the interface and implementations of classes and objects to provide more powerful structures • Behavioural Patterns – These deal with communication between groups of objects and classes 12th March 2004 Introduction to Design Patterns 27 Creational Patterns • Abstract Factory – Provides an interface to create and return one of several families of related objects • Builder – Separates the construction of a complex object from its representation so that several different representations can be created depending on the needs of the program • Factory Method – Provides a simple decision making method which returns one of several possible subclasses of an abstract base class depending on data provided 12th March 2004 Introduction to Design Patterns 28 14 Creational Patterns (cont’d) • Prototype – Starts with an initialised and instantiated class and copies or clones it to make new instances rather than creating new instances • Singleton – Provides a class of which there can be no more than one instance and provides a single global point of access to that instance 12th March 2004 Introduction to Design Patterns 29 Structural Patterns • Adapter – Converts the programming interface of one class into another for the benefit of a client • Bridge – Separates the interface of an object from its implementation so that the two can vary separately • Composite – Allows objects to be aggregated recursively by using a common interface to represent a composite and its components 12th March 2004 Introduction to Design Patterns 30 15 Structural Patterns (cont’d) • Decorator – Extends an object by adding responsibilities to it dynamically • Façade – Presents a single simple interface to a subsystem consisting of a number of interfaces • Flyweight – Increases program efficiency by allowing large numbers of objects of the same class to share state • Proxy – Represents a complex object with a simple one 12th March 2004 Introduction to Design Patterns 31 Behavioural Patterns • Chain of Responsibility – Allows a request to be passed along a sequence of objects until it reaches an object that knows how to handle it • Command – Encapsulates a command inside a class with a known interface so that the client does not have to know the mechanics of its execution • Interpreter – Given a language, defines a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language • Iterator – Allows a collection of data elements to be accessed through a standard interface 12th March 2004 Introduction to Design Patterns 32 16 Behavioural Patterns (cont’d) • Mediator – Allows classes to interact without knowing about each other • Memento – Captures and externalises the internal state of an object so that the object can be restored to this state later • Observer – Allows a number of objects to be notified whenever another object of interest changes • State – Allows an object to change its behaviour and appear as another class whenever its internal state changes 12th March 2004 Introduction to Design Patterns 33 Behavioural Patterns (cont’d) • Strategy – Defines a family of algorithms, encapsulates each one, and makes them interchangeable without affecting the client • Template Method – Allows an algorithm specification to be partially specified in a base class and completed in a derived class • Visitor – Applies an operation to a series of heterogeneous objects 12th March 2004 Introduction to Design Patterns 34 17 Summary - Why Use Design Patterns? • Proven solutions to OO problems • Common vocabulary for designers • Good way for beginners to become better designers • Makes standard libraries (Java, C++ etc.) easier to use • MAY help you at university • WILL help you in industry • BUT be careful not to overuse them 12th March 2004 Introduction to Design Patterns 35 Essential References • “Design Patterns: Elements of Reusable Software”, E. Gamma et al., Addison-Wesley, 1995 • “The Design Patterns Java Companion”, J. W. Cooper, Addison-Wesley, 1998 http://www.patterndepot.com/put/8/JavaPatterns.htm 12th March 2004 Introduction to Design Patterns 36 18 Other References • “Introduction to Patterns and Frameworks”, D. L. Levine and D. C. Schmidt, Department of Computer Science, Washington University http://www.cs.wustl.edu/~schmidt/PDF/patterns-intro4.pdf • “Patterns and Software: Essential Concepts and Terminology”, B. Appleton, 2000 http://www.enteract.com/~bradapp/docs/patterns-intro.html • “The Design Patterns Smalltalk Companion”,Alpert et al., Addison-Wesley, 1998 12th March 2004 Introduction to Design Patterns 37 Other Resources • The Patterns Homepage http://www.hillside.net/patterns/patterns.html • The Portland Pattern Repository http://c2.com/ppr/ • Douglas Schmidt’s Pattern Tutorials Page http://www.cs.wustl.edu/~schmidt/tutorials-patterns.html • JUnit Testing Framework – a good case study http://junit.sourceforge.net/doc/cookstour/cookstour.htm • Together 12th March 2004 Introduction to Design Patterns 38 19