Design Patterns
Total Page:16
File Type:pdf, Size:1020Kb
Design Patterns Partha Kuchana, Software Architecture Design Patterns in Java, Auerbach Publications, 2004. Contents I. Basic Patterns 1. Interface Pattern 2. Abstract Parent Class Pattern II. Creational Patterns III. Collectional Patterns 1. Composite Pattern 2. Visitor Pattern IV. Structural Patterns 1. Adapter Pattern 2 Contents V. Behavioral Patterns 1. Command Pattern 2. State Pattern 3 I. Basic Patterns 1. Interface Pattern 2. Abstract Parent Class Pattern 4 I.1 The Interface Pattern The Interface pattern can be used to design a set of service provider classes that offer the same service so that a client object can use different classes of service provider objects in a seamless manner without having to alter the client implementation. 5 I.1 The Interface Pattern Problem: Client-Service Provider Interaction An object that requests a service from another object is referred as a client object. An object that provides a service is called a service provider object. (a) One class of service provider 6 I.1 The Interface Pattern (b) More than one class of service providers It will not be able to make use of the different classes of service provider objects in a seamless manner. It requires changes to the design and implementation of the client and greatly reduces the reusability of the client by other objects. 7 I.1 The Interface Pattern Applying the Interface pattern, the common services offered by different service provider classes can be abstracted out and declared as a separate interface. Each of the service provider classes can be designed as implementers of this common interface. 8 I.1 The Interface Pattern Common interface with different service providers as implementers 9 I.1 The Interface Pattern An example: Let us build an application to calculate and display the salaries of different employees of an organization with the categorization of designations as listed in the following table Designations Category Programmer, Designer, Consultant Category-A Sales Rep, Sales Manager, Account Rep Category-B ... ... C-Level Executives Category-n ... ... 10 I. Interface This design works fine as long as the need is to calculate the salary for Category-A employees only and there is only one class of objects that provides this service. 11 I.1 The Interface Pattern Let us assume that the application also needs to calculate the salary of employees who are part of Category-B, such as sales representatives and account representatives, and the corresponding salary calculation service is provided by objects of a different class CategoryB 12 I.1 The Interface Pattern The main application will not be able to reuse the existing Employee class to represent different types of employees. This is because the Employee object expects the salary calculator to be always of the CategoryA type. 13 I.1 The Interface Pattern Applying the Interface pattern 14 15 16 Practice Questions 1. Design a Search interface that declares methods for searching an integer in an ordered list of integers. Design and implement two implementers - BinarySearch and LinearSearch - to conduct a binary and linear search of the list, respectively. 2. Pizza Mania (ref. Rice University) Pizza Mania is having a special on the same kind of pizza (i.e. same thickness and same ingredients). The special comes in two shapes: rectangular (4" by 6") for $4.99 and round (5" in diameter) for $3.99. Which one is the better deal? Write a program to solve this problem. 17 Practice Questions A pizza has a price and a shape. We want to compute the price/area ratio. It is the shape that intrinsically "knows" how to compute its area. A shape is an abstract concept. The area of a shape is an abstract computation. A rectangle is a concrete and specific shape. A rectangle knows its own width and height and therefore can compute its area in some concrete and specific way. A circle is a concrete and specific shape. A circle knows its own diameter and therefore can compute its area in some concrete and specific way. 18 19 I.2 The Abstract Parent Class Pattern This pattern is useful for designing a framework for the consistent implementation of the functionality common to a set of related classes. 20 I.2 The Abstract Parent Class Pattern In the Java there is no support for multiple inheritance. That means a class can inherit only from one single class. Hence inheritance should be used only when it is absolutely necessary. Whenever possible, methods denoting the common behavior should be declared in the form of a Java interface to be implemented by different implementer classes. 21 I.2 The Abstract Parent Class Pattern But interfaces suffer from the limitation that they cannot provide method implementations. This means that every implementer of an interface must explicitly implement all methods declared in an interface, even when some of these methods represent the invariable part of the functionality and have exactly the same implementation in all of the implementer classes. This leads to redundant code. The Abstract Parent Class pattern can be used in such cases without requiring redundant 22 method implementations. I.2 The Abstract Parent Class Pattern 23 I.2 The Abstract Parent Class Pattern An example: Let us consider the following operations as part of designing the representation of an employee. (1) Access employee attributes such as name and ID (2) Display employee data (3) Calculate compensation While Operation 1 and Operation 2 remain the same for all employees, the compensation calculation will be different for employees with different designations. 24 I.2 The Abstract Parent Class Pattern Each of the subclasses must implement the computeCompensation method. 25 I.2 The Abstract Parent Class Pattern Abstract Parent Class versus Interface As an alternate design strategy, we could design the employee representation as a Java interface, instead of designing it as an abstract class, with both the Consultant and the SalesRep classes as its implementers. 26 I.2 The Abstract Parent Class Pattern All methods specified in the interface remains the same for all implementers, this leads to redundant code in the application. The implementation of these invariable methods cannot be made part of the interface. An interface is used for the declaration purpose only. By designing the Employee class as an abstract class, the need for a redundant implementation can be eliminated. 27 II. Creational Patterns 28 III. Collectional Patterns 1. Composite Pattern 2. Visitor Pattern 29 III.1 Composite Patterns Every component or object can be classified into one of the two categories Individual Components or Composite Components, which are composed of individual components or other composite components. The Composite pattern is useful in designing a common interface for both individual and composite components. Client programs can view both the individual components and groups of components uniformly. 30 III.1 Composite Pattern In other words, the Composite design pattern allows a client object to treat both single components and collections of components in an identical manner. This can also be explained in terms of a tree structure. The Composite pattern allows uniform reference to both Nonterminal nodes (which represent collections of components or composites) and terminal nodes (which represent individual components). 31 III.1 Composite Pattern An example: Let us create an application to simulate the Windows/UNIX file system. The file system consists mainly of two types of components directories and files. Directories can be made up of other directories or files, whereas files cannot contain any other file system component. In this aspect, directories act as nonterminal nodes and files act as terminal nodes of a tree structure. 32 III.1 Composite Pattern Design Approach I Define a common interface for both directories and files in the form of an interface FileSystemComponent. The FileSystemComponent interface declares methods that are common for both file components and directory components. FileComponent and DirComponent are defined as implementers of the common FileSystemComponent interface 33 III.1 Composite Pattern 34 Design Approach I The client treats both the FileComponent and DirComponent objects in a uniform manner in the case of the common getComponentSize method. The client does need to distinguish when calling composite specific methods such as addComponent and getComponent defined exclusively in the DirComponent. Because these methods are not available with FileComponent objects, the client needs to check to make sure that the FileSystemComponent object35 it is working with is in fact a DirComponent object. Design Approach II The objective of this approach is to: Provide the same advantage of allowing the client application to treat both the composite DirComponent and the individual FileComponent objects in a uniform manner while invoking the getComponentSize method. 36 Design Approach II The FileSystemComponent provides the default implementation for these methods and is designed as an abstract class. 37 Design Approach II The default implementation of these methods consists of what is applicable to FileComponent objects. FileComponent objects are individual objects and do not contain other FileSystemComponent objects within. Hence, the default implementation does nothing and simply throws a custom CompositeException exception. The derived composite DirComponent class overrides these methods to provide custom implementation. 38 Practice Questions 1. There is an abstract notion of a list. 1. An empty list is a list. It has no element. 2. A non-empty list is a list. It has an element called first and an element called rest, which is itself another list. Design and implement an application to display all elements in a list. 2. A typical product database consists of two types of product components — product categories and product items. A product category is generally composite in nature. It can contain product items and also other product categories as its subcategories.