Design Patterns What is a Design Pattern? A "solution to a problem in context“; it represents a high-quality solution to a recurring problem in design Why use Design Patterns Success is more important than novelty Emphasis on writing and clarity of communication Qualitative validation of knowledge Good pattern arise from practical experience Recognize the importance of human dimensions in software development Success is more important than novelty Reusing standard designs with successful track record, often outweigh the few extra performance typically available from starting from scratch. Novelty can be a liability, because new techniques are often untested. Emphasis on writing and clarity of communication Patterns are documented both in literary style and technical document style – which makes easy communication. Very often projects fail because developers are unable to communicate good software deign, architectures and programming practices to each other. Using pattern improves communication and concisely articulating the structure and behavior of project. Good patterns arise from practical experience Appreciate and reward the creative progress that expert developers use to build high quality software system. Patterns are not to replace developers creativity – instead leverage the complexity and understandability of software systems Three Categories of Pattern Creational – makes systems independent of how objects are created,composed and represented – Singleton – Factory Behavioral – deals with algorithms and assignments of responsibilities between objects – Observer – Visitor – Cache Management Structural – are concerned with how classes and objects are composed to form larger structures – – – – Adapter Bridge Façade MVC The Singleton Pattern Creational Singleton – Context: It is very common to find classes for which only one instance should exist (singleton) – Problem: How do you ensure that it is never possible to create more than one instance of a singleton class? – Forces: The use of a public constructor cannot guarantee that no more than one instance will be created. The singleton instance must also be accessible to all classes that require it Singleton «Singleton» theInstance getInstance Company theCompany if (theCompany==null) theCompany= new Company(); Company «private» getInstance return theCompany; Behavioral Pattern: Observer Problem When an object changes state, notify all interested Context Multiple views of the same data (say, bar-charts and pie-charts) must be kept consistent with changes to the underlying data without any coupling among the views Key Participants A subject may have many dependent observers. All observers are notified whenever the subject undergoes change Observer: Structure observers Subject Attach(Observer) Detach(Observer) Notify() Observer Update() for all o in observers { o.Update() } ConcreteObserver ConcreteSubject GetState() SetState() subjectState subject return subjectState Update() observerState observerState = subject.GetState() Observer: Collaborations ConcreteSubjectA ConcreteObserverX ConcreteObserverY SetState() Notify() Update() GetState() Update() GetState() Observer: Implementation Observing more than one subject Who invokes Notify? – Have SetState invoke Notify – Require clients of Subject invoke Notify Dangling references to deleted subjects Call Notify only when Subject state is self-consistent How is change information transferred? – Push Model: Subject sends all details even if not required – Pull Model: Subject sends minimal information and Observers ask for details explicitly Selective notification of observers Behavioral Pattern: Visitor Problem Classes may be polluted with many distinct but unrelated operations Context Distributing operations like pretty-printing and type checking to various AST node classes in a compiler can lead to code that is difficult to maintain Adding a new operation would require changing all the node classes Key Participants Package related operations from each class into a single class, called a visitor Visitor: Structure Client Visitor VisitCEA(ConcreteElementA) VisitCEB(ConcreteElementB) ObjectStructure ConcreteVisitor1 Element Accept(Visitor) VisitCEA(ConcreteElementA) VisitCEA(ConcreteElementA) VisitCEB(ConcreteElementB) VisitCEB(ConcreteElementB) ConcreteElementA ConcreteElementB Accept(Visitor) OperationA() Accept(Visitor) OperationB() v.VisitCEA(this) ConcreteVisitor2 v.VisitCEB(this) Visitor: Collaborations anObjectStructure aConcreteElementA aConcreteVisitor aConcreteElementB Accept(aVisitor) VisitCEA(aConcreteElementA) OperationA() VisitCEB(aConcreteElementB) Accept(aVisitor) OperationB() Visitor: Implementation How does visitor add operations without changing them? – Double dispatch: operation that gets executed depends on the kind of request and types of two receivers(visitor and element) – This consolidates the operations in a visitor and uses Accept() as a double dispatch operation – Binding is run-time and extensions are easy Who is responsible for traversing the object structure? Responsibility could be in the object structure, visitor or a separate iterator object What about information hiding concepts? Structural Patterns:Façade The Façade pattern simplifies access to a related set of objects by providing one object that communicate with the set. By doing this you are decoupling business components from one another making designs more flexible and comprehensible. A Façade pattern enables a programmer to shield clients of classes from their complexity. This is done by providing an additional reusable object that hides most of the complexity of working with the other classes from client classes Using a Façade design pattern enables the developer to design classes to function in a clean and separate layer which allows for easier class reuse. Façade Class Diagram A Class diagram of a Façade pattern shows the general structure and sequence flow. The client object interacts with a Façade object that provides necessary functionality by interacting with the rest of the objects. If there is some additional functionality that is needed by only some clients, then instead of providing it directly, the Façade object may provide a method to access another object that does provide the functionality. The façade pattern shields client classes from complexity of the class they implement simplifying the use of multiple clients. Class Diagram Façade Class Diagram Implementing a Façade A Façade should provide a client object with a direct reference to a implementing class that the client should know about but hide the implementations that the client should not know about. This can be done through the use of private inner classes within the Façade classes. Session Facade Uses J2EE Session Beans to implement the façade pattern. Brings all the advantages of using a façade pattern to the J2EE Architecture, single interface, decoupling of objects, flexibility of reuse. A session façade also gives internet applications the advantage of calling server side business objects locally reducing network traffic between the client and the server. The session façade also acts as a mediator between business objects decoupling their interfaces and delegating calls to different objects. Sequence Diagram Call 1 Call 2 Call 3 Network Façade Sequence Diagram Call 1 Call 2 Call 3 Call 4 Network Cache Management The Cache Management pattern helps increase application performance by allowing fast access to objects that would otherwise take a long time to access. The pattern achieves this by keeping a copy of objects that are retrieved from a database or involve long computations to create. Once the copy of the object is created the application references the object attributes to retrieve important data.Cache Management is deciding which and how many objects to store in memory. A Cache Management pattern is based on the principle that keeping data in memory for fast access improves performance. This is a similar to a web browsers Cache that holds frequently visited web pages in memory for faster retrieval. Cache Management Classes The client is responsible for obtaining access to specified objects through a Cache Manager object. An ObjectKey is used to identify the object to be retrieved. The Cache Manager object handles requests for objects by calling the fetchObject method with an ObjectKey parameter. If an object exists it calls the fetchObject method. If the object needs to be created it calls the objectCreater createObject method. Cache Management Classes Cont. The object creator is responsible for creating objects that are not in the cache. The Cache object is the main object responsible for managing the collection of objects. An object is added to the cache by the addObject method and objects are retrieved with the fetchObject method. Cache Management Diagram Cache Management Implementation When implementing a Cache system you must consider using data structures that quickly find objects through it’s ObjectKey. Search operations should be faster then add or remove operations since they will be used most frequently. Cache Management optimization involves choices about statistical analysis, queuing theory, and performance tuning issues. Structural patterns:Model-ViewController The MVC design pattern is designed to decouple data representation, application behavior, and presentation. This pattern helps eliminate the problems that can happen during maintenance changes by making the components independent of each other. Class reuse can be difficult or impossible when a class is coupled to another class making them dependent. Model-View-Controller Cont MVC was originally used in Smalltalk and can de defined as: Model - The model represents enterprise data and the business rules that govern access to and updates of this data. Often the model serves as a software approximation to a real-world process, so simple real-world modeling techniques apply when defining the model. Model-View-Controller Cont II View -The view renders the contents of a model. It accesses enterprise data through the model and specifies how that data should be presented. It is the view's responsibility to maintain consistency in its presentation when the model changes. This can be achieved by using a push model, where the view registers itself with the model for change notifications, or a pull model, where the view is responsible for calling the model when it needs to retrieve the most current data. Model-View-Controller Cont III Controller – Components of the controller receive the client requests, process the request, or forward the request to other components that process the data, and then direct the request to a view component. Any web application component such as a JSP, Servlet, or EJB could be a controller component. Servlets are usually used because they are intended to receive requests and respond to clients. MVC Diagram Model -Encapsulate Application State -Respond to State Queries -Exposes Application functionality -Notify views of changes Controller -Defines application behavior -Maps user action to Model -Selects view for response View -Displays the Models -Requests updates from Models -Sends user info to Controller Method Invocation Event MVC Implementation MVC achieves decoupling using the controller to forward requests between the components involved. The Request Dispatcher method is used in the controller to forward the request or response information from other components and to display the Views that capture the Model output. This can also be achieved through a framework such as struts which uses the MVC pattern as it’s model for operation flow. Creational patterns:Factory Method Define an interface for creating an object, but let subclasses decide which class to instantiate. Lets a class defer instantiation to subclasses. Factory Method Cont. Document Example Consider a framework that can present multiple documents to the user. Abstract classes Application and Document Create two classes DrawingApplication and DrawingDocument. Application class will create documents when required – Open or New from menu. Factory Method Document Example cont. Application class only knows when a new document should be created, not what kind of document. It knows of the abstract classes but cannot instantiate them. When to Use the Factory Method A class cannot anticipate the class of objects it must create A class wants its subclasses to specify the objects it creates. Classes delegate responsibility to one of several helper subclasses and you want to localize the knowledge of which helper subclass is the delegate. Structure Creational patterns:Bridge Decouple an abstraction from its implementation so that the two can vary independently. Bridge Cont. When an abstract class can have several implementations, inheritance is used. Inheritance binds an implementation to the abstraction permanently, which makes modifications difficult. Bridge Example Consider a Window abstraction. User should be able to write applications on X Window System and IBM’s Presentation Manager (PM). Inheritance has two disadvantages in this case. Inheritance Disadvantages If you needed an IconWindow subclass of Window, you will need two new classes for implementation. Code is now platform-dependent Window Diagram Basic design of first implementation. Implement IconWindow How Bridge fixes this. The Bridge pattern addresses these problems by putting the Window abstraction and its implementation in separate class hierarchies. When to use bridge You want to avoid a permanent binding between abstraction and its implementation. Both the abstractions and their implementations should be extensible by subclassing. Code should not have to be recompiled if changes of implementation or abstraction occur. When to use Bridge cont. You want to share implementation among multiple objects and you want to hide this from the client. Structure Creational patterns:Adapter Convert the interface of a class into another interface clients expect. Lets classes work together that couldn’t otherwise because of incompatible interfaces. Drawing Class Consider a drawing editor that can draw basic shapes. LineShape and PolygonShape classes are easy to implement. TextShape is harder to implement so use third party object. How do you bring that object into the framework? Two Ways Inherit Shape’s interface and TextView’s implementation. Composing a TextView instance within a TextShape and implementing TextShape in terms of TextView’s interface. When to use Adapter You want to use an existing class, and its interface does not match the one you need. You want to create a reusable class that cooperates with unrelated or unforeseen classes. You need to use several existing subclasses , but it’s impractical to adapter their inteface by subclassing every one. Multiple Inheritance Composition