Upload
deisandeep7994
View
233
Download
0
Embed Size (px)
Citation preview
8/8/2019 Design Patterns-Compiled Notes
1/54
Design Patterns
Christopher Alexander says, Each pattern describes a problem which occurs over andover 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. Though he speaks about the buildings and towns, the same can be applied to object-oriented design
patterns.
If a problem occurs over and over again, the solution to the problem is used effectively.Such solution is known as a pattern. The design patterns are language independent
strategies used to provide a solution for any object oriented design problems.
Different Defns:1. Design patterns are solutions to the recurring design problems.
2. Design patterns constitute a set of rules describing how to accomplish certain tasks in
the realm of software development.
3. Design patterns focus more on reuse of recurring architectural design themes, whileframeworks focus on detailed design and implementation.
4. Patterns identify and specify abstractions that are above the level of single classes andinstances, or of components.
The design patterns are discovered rather than written. The process of finding out these
patterns is called pattern mining.
Design patterns are descriptions of communication between objects and classes
that are customized to solve a general design problem in a particular context. A
design pattern names, abstracts and identifies the main aspects of a commondesign structure that make it useful for creating a reusable object-oriented
design. It identified the participating classes and interfaces, their roles andcollaboration and the distribution of responsibilities. Each pattern focuses on aparticular design problem or issue. It describes when it applies and whether it
can be applied in view of other design constraints. It also describes the
consequences and the trade-offs of its use. A design pattern has four elements:
1. The pattern name: It can be used to describe a design problem, its solutions and
consequences in a word or two. It makes it easier to think about designs and
communicate them and their trade-offs to others easily.
2.The problem: The problem describes when the pattern can be applied. It explains thecontext of use for the pattern. It might also describe the class or object
structures that are symptoms of poor designs. It might also include a set of
conditions that must be met to apply the pattern.3. The solution: The solution describes the elements of the pattern that make up the
design. It also describes the structure of the pattern i.e the relationships,
responsibilities and the collaboration between different elements of the pattern.It basically gives the template that can be applied in different situations.
4. The consequences: These are the results and trade-offs that occur due to the usage of
the pattern. They are useful in choosing an alternative pattern. They also help
1
8/8/2019 Design Patterns-Compiled Notes
2/54
in evaluating the benefits and costs involved in using the pattern. The
consequences for s/w often concern space and time trade-offs.
Classification of Design Patterns:
Design patterns vary in their granularity and level of abstraction. The design patterns can
be classified by two criteria:1. Purpose.
2. Scope.
By purpose, the design patterns can be classified into:
Creational patterns: They concern the process of object creation.
Structural patterns: They deal with the composition of classes or objects.Behavioral patterns: They characterize the ways in which classes or objects interact and
distribute responsibility.
By scope, the design patterns can be classified into:
Class patterns: They deal with the relationships between classes and their subclasses.These relationships are established through inheritance, so they are static-fixed
at compile-time.
Object patterns: They deal with the object relationships, which can be changed at run-
time and are more dynamic.
The creational class patterns defer some part of the object creation to subclasses, and
object creational patterns defer it to another object. The structural class patterns use inheritance to compose classes whereas the structural object
patterns describe ways to assemble objects. The behavioral class patterns use
inheritance to describe algorithms and flow of control, whereas the behavioralobject patterns describe how a group of objects cooperate to perform a task that
no single object can carry out alone.
The different design patterns catalog grouped into different categories is as follows:
PURPOSE:
Creational Patterns
1. Abstract factory
2. Builder
3. Factory Method4. Prototype
5. Singleton
Structural Patterns
1. Adapter
2. Bridge
3. Composite4. Decorator
5. Faade
2
8/8/2019 Design Patterns-Compiled Notes
3/54
6. Flyweight
7. Proxy
Behavioral
1. Chain of Responsibility2. Command
3. Interpreter4. Iterator5. Mediator
6. Memento
7. Observer
8. State9. Strategy
10. Template Method
11. Visitor
SCOPE:
Class
1. Factory2. Adapter
3. Interpreter
4. Template Method
Object
1. Abstract Factory
2. Builder
3. Prototype4. Singleton
5. Adapter
6. Bridge7. Composite
8. Decorator
9. Faade10. Flyweight
11. Proxy
12. Chain of Responsibility13. Command
14. Iterator15. Mediator16. Memento
17. Observer
18. State
19. Strategy
3
8/8/2019 Design Patterns-Compiled Notes
4/54
Principles of design patterns:
1. Programming to an interface, not an implementation:Class versus Interface implementation:
To understand this, it is imp. to understand the difference between a class and a type. An
objects class defines how the object is implemented. The class defines theobjects internal state and the implementation of its operations whereas; an
objects type only refers to its interface- the set of requests to which it can
respond. An object can have many types, and objects of different classes can
have the same type. There is a close relationship between a class and the type.Because a class defines the operations an object can perform, it also defines the
objects type.
Class inheritance defines an objects implementation in terms of another objects
implementation. Its a mechanism for code and representation sharing.Interface inheritance describes when an object can be used in place of another.
Class inheritance is a mechanism for extending application functionality by reusing
functionality in parent classes. It lets us to define a new object rapidly in terms
of an old one. It lets us to get new implementations almost for free. Inheriting
what we need from existing classes. If inheritance is used properly, all classesderived from an abstract class will share its interface. This implies that a
subclass merely overrides or adds operations and does not hide the operations
of the parent class.There are two benefits to manipulating objects solely in terms of the interface defined by
abstract classes:
Clients remain unaware of the specific types of objects they use, as long as the objectsadhere to the interface that clients expect.
Clients remain unaware of the classes that implement these objects. Clients only know
about the abstract class defining the interface.
To implement this principle, we should not declare variables to be instances of particular
concrete classes. Instead, we should commit only to an interface by an abstract
class. Creational patterns ensure that the system is written in terms ofinterfaces, not implementations.
2. Favor Object composition over class inheritance:
Inheritance versus composition:
Class inheritance lets us to define the implementation of one class in terms of anothers.Reuse by subclassing is referred to as white-box reuse. The term white-box
refers to visibility: With inheritance, the internals of parent class are often
visible to subclasses.
4
8/8/2019 Design Patterns-Compiled Notes
5/54
Object composition is an alternative to class inheritance. In this technique, new
functionality is obtained by assembling or composing simple objects into a
more complex object or functionality. Object composition is defineddynamically at runtime through objects acquiring references to other objects.
Any object can be replaced by any other runtime as long as it they have the
same type.
Disadvantages of inheritance:The implementations inherited from the parent classes cant be changed at runtime
because inheritance is defined statically at compile time.
Parent classes often define at least a part of their subclasses physical representation. As
inheritance exposes a subclass to details of it s parents implementation, itsoften said that inheritance breaks encapsulation. If any implementation in the
parent class is changed, the subclass also has to be changed.
If any aspect of inherited implementation is not appropriate for the new domain, then the
parent class must be rewritten or replaces by something more appropriate. Thisdependency limits flexibility and ultimately reusability.
Advantages of composition:
It helps to keep each class encapsulated and focused on one task.
The classes and class hierarchies will remain less and will less likely grow into
unmanageable monsters.A design based on object composition will have more objects and the systems behavior
will depend on their interrelationships instead of being defined in one class.
Ideally, you shouldn't have to create new components to achieve reuse. You should beable to get all the functionality you need just by assembling existing components through
object composition. But this is rarely the case, because the set of available components is
never quite rich enough in practice. Reuse by inheritance makes it easier to make newcomponents that can be composed with old ones. Inheritance and object composition thus
work together.
Delegation:
Delegation is a way of making composition as powerful as delegation. In delegation, two
objects are involved in handling a request; the receiving objects that receives the request
delegates the operations to the delegate. This is analogous to subclasses deferring therequests to the parent classes. But instead of inheritance, the receiving class will have a
reference to the delegate class and explicitly forwards the request to that reference.
The main advantage of delegation is that it makes it easy to compose behaviors at run-time and to change the way theyre composed.
Delegation is heavily used in the State, Strategy and Visitor patterns. Mediator,
Chain of Responsibility and Bridge patterns use delegation less heavily.
3. Designing for change:
The key to maximizing reuse lies in anticipating new requirements and changes to
existing requirements, and in designing systems so that they can evolve accordingly. To
5
8/8/2019 Design Patterns-Compiled Notes
6/54
design a system thats robust to such changes, it is important to consider how the system
might change over its lifetime. If a design doesnt take into account the changes that
might occur in future, it might lead to redesign involving class redefinition andreimplementation, client modification, and retesting.
Some common causes of redesign are:
1. Creating an object by specifying a class explicitly:Specifying a class name when you
create an object commits you to a particular implementation instead of a particularinterface. This commitment can complicate future changes. To avoid it, create objects
indirectly.
2. Dependence on specific operations: When you specify a particular operation, you
commit to one way of satisfying a request. By avoiding hard-coded requests, you make iteasier to change the way a request gets satisfied both at compile-time and at run-time.
3.Dependence on object representations or implementations:Clients that know how an
object is represented, stored, located, or implemented might need to be changed when the
object changes. Hiding this information from clients keeps changes from cascading.4. Algorithmic dependencies: Algorithms are often extended, optimized, and replaced
during development and reuse. Objects that depend on an algorithm will have to changewhen the algorithm changes. Therefore algorithms that are likely to change should be
isolated.
5. Tight coupling:Classes that are tightly coupled are hard to reuse in isolation, since
they depend on each other. Tight coupling leads to monolithic systems, where you can'tchange or remove a class without understanding and changing many other classes. The
system becomes a dense mass that's hard to learn, port, and maintain. Loose coupling
increases the probability that a class can be reused by itself and that a system can belearned, ported, modified, and extended more easily. Design patterns use techniques such
as abstract coupling and layering to promote loosely coupled systems.
6. Extending functionality by subclassing:Customizing an object by subclassing oftenisn't easy. Every new class has a fixed implementation overhead (initialization,
finalization, etc.). Defining a subclass also requires an in-depth understanding of the
parent class. For example, overriding one operation might require overriding another. Anoverridden operation might be required to call an inherited operation. And subclassing
can lead to an explosion of classes, because you might have to introduce many new
subclasses for even a simple extension. Object composition in general and delegation in
particular provide flexible alternatives to inheritance for combining behavior. Newfunctionality can be added to an application by composing existing objects in new ways
rather than by defining new subclasses of existing classes. On the other hand, heavy use
of object composition can make designs harder to understand. Many design patternsproduce designs in which you can introduce customized functionality just by defining one
subclass and composing its instances with existing ones.
7. Inability to alter classes conveniently: Sometimes you have to modify a class thatcan't be modified conveniently. Perhaps you need the source code and don't have it (as
may be the case with a commercial class library). Or maybe any change would require
modifying lots of existing subclasses. Design patterns offer ways to modify classes in
such circumstances.
6
8/8/2019 Design Patterns-Compiled Notes
7/54
Frameworks:
A framework is a set of cooperating classes that make up a reusable design for a specificclass of software. The framework dictates the architecture of your application. It will
define the overall structure, its partitioning into classes and objects, the key
responsibilities thereof, how the classes and objects collaborate, and the thread of control.A framework predefines these design parameters so that you, the application
designer/implementer, can concentrate on the specifics of your application. The
framework captures the design decisions that are common to its application domain.Frameworks thus emphasize design reuse over code reuse, though a framework will
usually include concrete subclasses you can put to work immediately.
Differences between a framework and a design pattern:
1. Design patterns are more abstract than frameworks.Frameworks can be embodied incode, but only examples of patterns can be embodied in code. A strength of frameworks
is that they can be written down in programming languages and not only studied but
executed and reused directly. In contrast, the design patterns in this book have to be
implemented each time they're used. Design patterns also explain the intent, trade-offs,and consequences of a design.
2. Design patterns are smaller architectural elements than frameworks. A typicalframework contains several design patterns, but the reverse is never true.
3. Design patterns are less specialized than frameworks. Frameworks always have a
particular application domain. A graphical editor framework might be used in a factory
simulation, but it won't be mistaken for a simulation framework. In contrast, the design patterns in this catalog can be used in nearly any kind of application. While more
specialized design patterns than ours are certainly possible (say, design patterns for
distributed systems or concurrent programming), even these wouldn't dictate anapplication architecture like a framework would.
Design Pattern Aspect(s) That Can Vary:
Design Patterns Aspects that can vary
Abstract Factory families of product objects
Builder how a composite object gets created
Factory Method subclass of object that is instantiated
Prototype class of object that is instantiated
Singleton the sole instance of a class
Adapter interface to an object
Bridge implementation of an object
Composite structure and composition of an objectDecorator responsibilities of an object without subclassing
Facade interface to a subsystem
Flyweight storage costs of objects
Proxy how an object is accessed; its location
Chain of Responsibility object that can fulfill a request
Command when and how a request is fulfilled
Interpreter grammar and interpretation of a language
7
8/8/2019 Design Patterns-Compiled Notes
8/54
Iterator how an aggregate's elements are accessed, traversed
Mediator how and which objects interact with each other
Memento what private information is stored outside an object, and when
Observer number of objects that depend on another object; how the
dependent objects stay up to date
State states of an objectStrategy an algorithm
Template Method steps of an algorithm
Visitor operations that can be applied to object(s) without changing their
class(es)
Creational Patterns:
1. Singleton pattern: It is of a class where there can be no more than one instance. It
provides a single global point of access to that instance.
This is used when there is a need to make sure that there can be only one instance of a
class. The easiest way is to embed a static variable inside the class that is set on the firstinstance and check for each time when the constructor is called. This is because a static
variable can have only one instance.
A way to check if only one instance is created for a class is to throw an exception when
more than one instance is created.
Another way is to create a final class like Math class which has all static members, for
which any instance cannot be created directly but can only call the static methods of the
class.
The third way is to create a singleton pattern using static methods to create and keeptrack of instances. The constructor of the class is made private to ensure that an instancecan be created only from within the static method of the class.
Consequences of a singleton:1. It can be difficult to subclass a Singleton, since this can work only if the base has not
yet been instantiated.
2. You can easily change a singleton to allow a small number of instances where this is
allowable and meaningful.
Examples:CASE 1:class SingletonException extends RuntimeException{//new exception type for singleton classespublic SingletonException(){super();}//-----------------------------------------------
8
8/8/2019 Design Patterns-Compiled Notes
9/54
public SingletonException(String s){super(s);}}
class PrintSpooler
{//this is a prototype for a printer-spooler class//such that only one instance can ever existstatic boolean instance_flag=false; //true if 1 instancepublic PrintSpooler() throws SingletonException{if (instance_flag)throw new SingletonException("Only one spooler allowed");elseinstance_flag = true; //set flag for 1 instanceSystem.out.println("spooler opened");}//-------------------------------------------public void finalize(){
instance_flag = false; //clear if destroyed}}
public class singleSpooler{static public void main(String argv[]){PrintSpooler pr1, pr2;//open one spooler--this should always workSystem.out.println("Opening one spooler");try{pr1 = new PrintSpooler();}
catch (SingletonException e){System.out.println(e.getMessage());}//try to open another spooler --should failSystem.out.println("Opening two spoolers");try{pr2 = new PrintSpooler();}catch (SingletonException e){System.out.println(e.getMessage());}}}
Then, if we execute this program, we get the following results:Opening one spoolerprinter openedOpening two spoolers
Only one spooler allowed
CASE 2:final class PrintSpooler{//a static class implementation of Singleton patternstatic public void print(String s){System.out.println(s);
9
8/8/2019 Design Patterns-Compiled Notes
10/54
}}//==============================public class staticPrint{public static void main(String argv[]){
Printer.print("here it is");}}
CASE 3:class iSpooler{//this is a prototype for a printer-spooler class such that only one instancecan ever existstatic boolean instance_flag = false; //true if 1 instance//the constructor is privatized-//but need not have any contentprivate iSpooler() { }static public iSpooler Instance() {if (! instance_flag)
{instance_flag = true;return new iSpooler(); //only callable from within}elsereturn null; //return no further instances}//-------------------------------------------public void finalize(){instance_flag = false;}}
Factory Pattern
It deals with the problem of creating objects without specifying the exact class of object
that will be created. This pattern handles this problem by defining a separate method for
creating objects which subclasses can then override to specify the derived type of productthat will be created.
Factory pattern promotes loose coupling by eliminating the need to bind application
specific classes into the code.Factory pattern is all about:
Define an interface for creating an object, but let the subclasses decide which class toinstantiate. The factory method lets a class defer instantiation to subclasses. Thus, as
defined by Gamma et al, The Factory method lets a class defer instantiation tosubclasses.
10
8/8/2019 Design Patterns-Compiled Notes
11/54
When to use a factory pattern:
A class cant anticipate which kind of class of objects it must create.
A class uses its subclasses to specify which objects it creates.
You want to localize the knowledge of which class gets created.
Variations of factory pattern that make it easy to recognize:
The base class is abstract and the pattern must return a complete working class.
The base class contains default methods and is only subclassed for cases where
the default methods are insufficient. Parameters are passed to the factory telling it which of several class types to
return. In this case, classes may share the same method names but nay do
something quite different.
Common Usage:
It is common in toolkits and frameworks where library code needs to create
objects of types which may be subclassed by applications using the framework.
This is because frameworks exist at an abstract level. Usually they do not know
and should not be concerned about instantiating specific objects. They need todefer the decisions about specific objects to the users of the framework.
Parallel class hierarchies often require objects from one hierarchy to be able to
create appropriate objects from another.There is a principle of object-oriented design known as the Dependency Inversion
Principle (DIP). This principle tells that we should try to avoid depending on things
that are concrete. For example, given the choice between holding a reference to a List or
Creator
+ factory( ) : Product
ConcreteCreator
+ factory( ) : Product
Product
11
8/8/2019 Design Patterns-Compiled Notes
12/54
its derivative LinkedList, we should choose the base class List. In other words, rather
than writing
LinkedList balls = new LinkedList ( );Its better to write,
List balls = new LinkedList ( );
The DIP says: "Depend on abstractions, not on concretions .In theFactory Method
pattern, we add abstract make methods to the class that needs to create the instances of the
objects. Then, in derivatives of that class, we implement those make methodsappropriately.
Logical Model:
There are countless variations of the Factory pattern, although most variants typically use
the same set of primary actors, a client, a factory, and a product. The client is an object
that requires an instance of another object (the product) for some purpose. Rather thancreating the product instance directly, the client delegates this responsibility to the
factory. Once invoked, the factory creates a new instance of the product. To put it simply,the client uses the factory to create the instance of the product. The factory completely
abstracts the creation and initialization of the product from the client. This indirection
enables the client to focus on its discrete role in the application without concerning itself
with the details of how the product is created. Thus, as the product implementationchanges over time, the client remains unchanged.
The most important aspect of this pattern is that the client is abstracted both from
the type of product and the type of factory used to create the product. Presuming that theproduct interface is invariant, this enables the factory to create any product type it deems
appropriate. Furthermore, presuming that the factory interface is invariant, the entire
factory along with the associated products it creates can be replaced in a wholesalefashion. Both these radical changes occur without any change to the client.
Factory pattern logical Model
Physical Model:
Most implementations of the factory pattern use two abstract classes, Factory and
Product to provide the invariant interfaces discussed in the logical model. The Client
uses an instance of a concrete subclass of Factory (ConcreteFactory) to create aninstance of a concrete Product subclass (ConcreteProduct). Since all the variables,
parameters and the method return values are typed to the Factory and Product abstract
classes, the Client is unaware of these subclasses.
Client Factory Productuses creates
12
8/8/2019 Design Patterns-Compiled Notes
13/54
Factory Pattern Physical Diagram
In Java, iterator ( ) method is a factory method. This method returns the right type ofiterator for the collection being asked for it.
The Factory Method Pattern: Key Features
Intent Define an interface for creating an object, but let subclasses decidewhich class to instantiate. Defer instantiation to subclasses.
Problem A class needs to instantiate a derivation of another class, but doesn't
know which one. Factory Method allows a derived class to make
this decision.
Solution A derived class makes the decision on which class to instantiate and
how to instantiate it.
Participants and
collaborators
Product is the interface for the type of object that the Factory
Method creates. Creator is the interface that defines the Factory
Method.
Consequences Clients will need to subclass the Creator class to make a particularConcreteProduct.
Implementation Use a method in the abstract class that is abstract (pure virtual in C+
+). The abstract class' code refers to this method when it needs to
instantiate a contained object but does not know which particular
object it needs.
Sample Code
Consider a simple case in which we could use a Factory class. Suppose we have an entry
form and we want to allow the user to enter his name either as "firstname lastname" or as
Factory Product
ConcreteProductConcreteFactory
13
Client
8/8/2019 Design Patterns-Compiled Notes
14/54
"lastname, firstname." We'll make the further simplifying assumption that we will always
be able to decide the name order by whether there is a comma between the last and first
name.
This is a pretty simple sort of decision to make, and you could make it with a simple if
statement in a single class, but let's use it here to illustrate how a factory works and whatit can produce. We'll start by defining a simple base class that takes a String and splits it
(somehow) into two names:
public class Namer {
//base class extended by two child classes
protected String last; //split name
protected String first; //stored here
public String getFirst() {
return first; //return first name
}public String getLast() {
return last; //return last name}
}
In this base class, we don't compute any names as such, but we do provideimplementations of the getFirst and getLast methods. We'll store the split first and
last names in the Strings first and last, and, since the subclasses will need access to these
variables, we'll make them protected.
Now we can write two very simple subclasses that split the name into two parts in theconstructor. In the FirstFirst class, we make the simplifying assumption that everything
before the last space is part of the first name.
public class FirstFirst
extends Namer {//extracts first name from last name
//when separated by a space
public FirstFirst(String s) {int i = s.lastIndexOf(" "); //find sep space
if (i > 0) {first = s.substring(0, i).trim();last = s.substring(i + 1).trim();
} else {
first = ""; // if no spacelast = s; // put all in last name
}
}
14
8/8/2019 Design Patterns-Compiled Notes
15/54
}
And in the LastFirst class, we assume that a comma delimits the last name. In bothclasses, we also provide error recovery in case the space or comma does not exist.
public class LastFirst extends Namer {
// extracts last name from first name
// when separated by a commapublic LastFirst(String s) {
int i = s.indexOf(","); //find comma
if (i > 0) {
last = s.substring(0, i).trim();first = s.substring(i + 1).trim();
} else {
last = s; //if no comma,
first = ""; //put all in last name}
}}
Building the Simple Factory
Now our simple Factory class is extremely simple. We just test for the existence of a
comma and then return an instance of one class or the other.
public class NamerFactory {//Factory decides which class to return based on
//presence of a comma
public Namer getNamer(String entry) {//comma determines name order
int i = entry.indexOf(",");
if (i > 0)
return new LastFirst(entry);else
return new FirstFirst(entry);
}}
SAMPLE 2:
Implementation of Factory Pattern:
Abstract Class:
package factoryPattern;
15
8/8/2019 Design Patterns-Compiled Notes
16/54
public class DisplayGrantedShares {
public void displayShares(){
System.out.println("Select an appropriate type of share");}
}Concrete Implementations of Products:
class AwardsDisplay extends DisplayGrantedShares{public void displayShares(){
System.out.println("Displaying Granted Awards");
}
}
class OptionsDisplay extends DisplayGrantedShares{
public void displayShares(){
System.out.println("Displaying Granted Options");}
}
class PurchaseDisplay extends DisplayGrantedShares{
public void displayShares(){
System.out.println("Displaying Granted Purchases");}
}
Factory Class:
package factoryPattern;
public class SharesDisplayFactory {
String shareType;
public SharesDisplayFactory(String shareType){this.shareType=shareType;
display().displayShares();
}
public DisplayGrantedShares display(){
if(shareType.equalsIgnoreCase("Awards")){return new AwardsDisplay();
}else if(shareType.equalsIgnoreCase("Options")){
return new OptionsDisplay();
}else if(shareType.equalsIgnoreCase("Purchases")){
16
8/8/2019 Design Patterns-Compiled Notes
17/54
return new PurchaseDisplay();
}else{
return new DisplayGrantedShares();}
}
}
Client Class:
package factoryPattern;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ShareDisplayClient {
public static void main(String[] args) {
String shareType=null;
System.out.println("Please Enter the Share Type to display : ");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));try {
shareType=br.readLine();
} catch (IOException ex) {ex.printStackTrace();
}
new SharesDisplayFactory(shareType);
}
}
ABSTRACT FACTORY PATTERN
Abstract factory pattern provides a way to encapsulate a group of individual factories that
have a common theme. This pattern is one level abstraction higher than factory pattern. Itis an object creational pattern. Sometimes several objects need to be instantiated in a
coordinated fashion. For example, when dealing with user interfaces, the system might
need to use one set of objects to work on one operating system and another set of objects
17
8/8/2019 Design Patterns-Compiled Notes
18/54
to work on a different operating system. The Abstract Factory pattern ensures that the
system always gets the correct objects for the situation.
Intent:
The intent of abstract factory pattern is to provide an interface for creating families ofrelated or dependent objects without specifying their concrete classes.
When to use:
The client should be independent of how the products are created.
The application should be configured with one of multiple families of products.
Objects need to be created as a set, in order to be compatible.
You want to provide a collection of classes and you want to reveal just theircontracts and their relationships, not their implementations.
Description:
For example, an application needs to use a variety of resources or operating
environments. Some common ones include:
Windowing (An applications GUI)
A file system
Communication with other applications and systems.
In this sort of application, you want to make the application flexible enough to use a
variety of these resources without having to recode the application each time a new
resource is added.
An effective way to solve this problem is to define a generic resource creator, theAbstract factory. The factory has one or more create methods, which can be called to
produce generic resources or abstract products. Java ("Java technology") runs on manyplatforms, each with many different implementations of a file system or windowing. The
solution Java has taken to abstract the concepts of files and windowing and not show the
concrete implementation. You can develop the application using the generic capabilitiesof the resources as though they represented real functionality. During runtime,
ConcreteFactories and ConcreteProducts are created and used by the application. The
concrete classes conform to the contract defined by the AbstractFactory andAbstractProducts, so the concrete classes can be directly used, without being recoded or
recompiled.
Implementation:
Abstract Factory class diagram
18
8/8/2019 Design Patterns-Compiled Notes
19/54
You typically use the following to implement the Abstract Factory pattern:
AbstractFactory An abstract class or interface that defines the create methods
for abstract products.
AbstractProduct An abstract class or interface describing the general behaviorof the resource that will be used by the application.
ConcreteFactory A class derived from the abstract factory. It implements create
methods for one or more concrete products.
ConcreteProduct A class derived from the abstract product, providing an
implementation for a specific resource or operating environment.
Benefits:
An Abstract Factory helps to increase the overall flexibility of an application.This flexibility manifests itself both during design time and runtime.
During design, you do not have to predict all future uses for an application.
Instead, you create the generic framework and then develop implementationsindependently from the rest of the application. At runtime, the application can
easily integrate new features and resources.
19
8/8/2019 Design Patterns-Compiled Notes
20/54
A further benefit of this pattern is that it can simplify testing the rest of the
application. Implementing a TestConcreteFactory and TestConcreteProduct issimple; it can simulate the expected resource behavior.
Difference between abstract factory and factory:
The abstract factory pattern provides an interface for creating a family of objectswhereas factory method provides an interface for creating one object
Factory is a class creational pattern and abstract factory is an object creational
pattern.
The difference lies in how dynamic the substitution needs to be. In bothcases the Product and the Factories to produce them are generalizations.
The difference is that in Factory Method the subclasses in each
generalization map 1:1 to each other while in Abstract Factory the
Factory subclasses map 1:* to Product subclasses.Thus in Factory Method a concrete factory object can instantiate exactly
one flavor of one Product. But in Abstract Factory a single concrete
factory object can instantiate a different flavor of Product from eachof multiple Product generalizations. IOW, one uses Factory Method when
there is only one family of products and one uses Abstract Factory when
there are construction similarities across multiple families of products.
Provides an interface for creating families of related or dependent objects withoutspecifying their concrete classes.
Applicability
Need to abstract from details of implementation of products
Need to have multiple families of products
Need to enforce families of products that must be used together
Need to hide product implementations and just present interfaces
20
8/8/2019 Design Patterns-Compiled Notes
21/54
Consequences
Isolates concrete classes
Makes exchanging product families easy
Promotes consistency among products
Supporting new kinds (in each family) of products in difficult
Creational Patterns: Class and Object
The class creational pattern uses inheritance effectively in the instantiation process and
the object creational pattern uses delegation to get the job done.
Sample 1:package abstractfactory;
publicclass Workstation extends Computer {
public Parts getRAM() { returnnew Parts("1 GB");}
public Parts getProcessor() {
returnnew Parts("Intel P 3");}
public Parts getMonitor() {
returnnew Parts("19 inches");}
}
package abstractfactory;publicclass Server extends Computer{
public Parts getRAM() { returnnew Parts("4 GB");
}
public Parts getProcessor() { returnnew Parts("Intel P 4");
}
public Parts getMonitor() {
returnnew Parts("17 inches");}
}
publicclass PC extends Computer {
public Parts getRAM() { returnnew Parts("512 MB");
}
21
8/8/2019 Design Patterns-Compiled Notes
22/54
public Parts getProcessor() {
returnnew Parts("Celeron");}
public Parts getMonitor() {
returnnew Parts("15 inches");}
}
publicabstractclass Computer {
publicabstract Parts getRAM();
publicabstract Parts getProcessor();
publicabstract Parts getMonitor();
}
publicclass ComputerType { private Computer comp;
publicstaticvoid main(String[] args) {
ComputerType type = new ComputerType();
Computer computer = type.getComputer("PC");
System.out.println("Monitor:"+computer.getMonitor().getSpecification());
System.out.println("RAM:"+computer.getRAM().getSpecification());
System.out.println("Processor:"+computer.getProcessor().getSpecification());}
public Computer getComputer(String computerType) {
if (computerType.equals("PC"))comp = new PC();
elseif(computerType.equals("Workstation"))comp = new Workstation();
elseif(computerType.equals("Server"))comp = new Server();
return comp;}
}
publicclass ComputerType { private Computer comp;
publicstaticvoid main(String[] args) {
ComputerType type = new ComputerType();
Computer computer = type.getComputer("PC");
22
8/8/2019 Design Patterns-Compiled Notes
23/54
System.out.println("Monitor:"+computer.getMonitor().getSpecification());
System.out.println("RAM:"+computer.getRAM().getSpecification());
System.out.println("Processor:"+computer.getProcessor().getSpecification());
}
public Computer getComputer(String computerType) { if (computerType.equals("PC"))
comp = new PC(); elseif(computerType.equals("Workstation"))
comp = new Workstation(); elseif(computerType.equals("Server"))
comp = new Server(); return comp;
}}
Prototype Pattern
Intent:
"Specify the kinds of objects to create using a prototypical instance, and create new
objects by copying this prototype.
Intent seen through real life:
The prototype pattern suggests that when you have a requirement for a product class,instead of trying to create the object from scratch, you pick the best candidate from a set
of possible matches and you tweak the object to fit the exact characteristics required. So,
the idea behind the prototype pattern is to create a new object by starting with one ofseveral basic designs which have most of the features which you currently need to be in
the new object. The client will then tweak the object which is returned so that it looks andbehaves exactly in the manner that is required for the current situation.
In the prototype pattern, we have several prototype-classes which are classes with basic
features that we may want-already built in. Each prototype is a point-of-departure for
coming up with the specific design which we require. But using one of the prototypessaves us from having to construct the product from scratch. We just make a few changes
here and there and we have met the requirements.
Sitting between the client and the prototypes are the prototype-manager and the Abstract-
Prototype. The prototype manager is just a class which holds a reference to the
Prototypes which are available for use by the client, (much like a catalogue has a set ofpictures of products the mail-order shopper can order). The client will forward requests to
the prototype manager to return one of the prototypes it "knows" about. There is usually a
bit of logic which the Prototype manager performs to figure out which Prototype to
return, but that's the basic job of the prototype manager.
Now here's the trick with the Prototype pattern. The Abstract-Prototype. This class
governs the behaviour of the Prototypes and ensures that they implement a method for
23
8/8/2019 Design Patterns-Compiled Notes
24/54
copying or "cloning" themselves along with the functionality that the client is actually
interested in. If you are going to make a lot of changes to the prototype after you get
access to it, and the same prototype may be needed-untouched-by another client later on,then you have to ensure that the first client gets a true copy of the prototype and not just
an object reference to the same prototype.
Intent seen through the O/S and applications:
If you look at the new document dialog box in Word or Excel, you will see the prototype
pattern in principle. When creating a Fax Letter head, you wouldn't want to start fromscratch. Instead you will select from one of the templates provided with Word.. The user
simply customizes the basic document to make it fit the exact purpose intended, by filling
in the addressee's name, phone number, the date and so on.
In this case, the concrete-prototypes are the individual FAX templates, the Prototype
manager is the Templates Dialog box, the client is your new Word FAX cover page and
the abstract-prototype is the requirements which all Fax-Templates must meet
(specification for headings etc)
Motivation:
24
8/8/2019 Design Patterns-Compiled Notes
25/54
Problem:
The GraphicTool class belongs to the framework, while the graphical classes are
application-specific, so the GraphicTool class doesn't know how to create graphicalobjects and then operate on them.
Solution:Method 1:
This method will produce many subclasses that are different only in the kind of musicobjects they instantiate.
Method 2: (Prototype Pattern)
25
8/8/2019 Design Patterns-Compiled Notes
26/54
To create a new graphical object, the prototypical instance of the specific graphical class
is passed as parameter to the constructor of the GraphicTool class. The GraphicTool class
can then use this prototype to clone a new object and operate on it.Therefore, if all the Graphic subclasses support a Clone operation, then the GraphicTool
Class can clone any kind of Graphic.
Prototype Pattern can also be used to reduce the number of classes. E.G. the WholeNote
and HalfNote class only differ in that they have different bitmaps and durations. Insteadof defining a subclass of MusicalNote class for each type of notes, we can make the
MusicalNote class concrete, and the note objects can be instances of the same
MuscialNote class initialized with different setting. Therefore, for GraphiTool class, tocreate a new WholeNote object is to clone a prototype that is MuscialNote object
initialized to be a WholeNote.
A
pplicabilityUse Prototype Pattern when a system should be independent of how its products arecreated, composed, and represented, and
1. When the classes to instantiate are specified at run-time; or for example, the dynamic
loaded class won't be specified until it is loaded, the instance of this kind of classes couldonly be created at run-time.
26
http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f3%23f3http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f3%23f38/8/2019 Design Patterns-Compiled Notes
27/54
2. To avoid building a class hierarchy of factories that parallels the class hierarchy of
products; orIn Abstract Factory Pattern, we need to build concrete factory subclass for
each product family even if they differ only slightly. Using Prototype Pattern, We onlyneed one concrete factory. The concrete factory is parameterized with the prototypical
instance of each product in the family. The concrete factory then uses these prototypes to
create new objects.
3. When instances of a class can have one of only a few different combinations of state.
E.G. instances of MusicalNotes class can be either WholeNote object or HalfNote object.Instead of using new MusicalNote with approriate state information each time to create a
new WholeNote (HalfNote) object, we can clone a WholeNote (HalfNote) prototype to
create a new WholeNote (HalfNote) object.
Structure
Participants
Prototype: declares an interface for cloning itself.
ConcretePrototype: implements the operation for cloning itself.
Client: creates a new object by asking a prototype to clone itself.
27
http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f8%23f8http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f4%23f4http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f8%23f8http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f4%23f48/8/2019 Design Patterns-Compiled Notes
28/54
Collaborations
A client asks a prototype to clone itself.
Consequences
1 .Isolating concrete product classes from the client.Because the prototype encapsulates the responsibility and the process of creating objects,
it isolate clients from implementation class.
2. Dynamically adding and removing products at run-time:
By using prototype manager, client can install and remove prototypes of new concrete
product classes at run-time. The prototype manager would be explained in details in theimplementation section.
3. Specifying new objects by varying values:
New objects can be created by simply changing the value of the prototype reference.
4. Specifying new objects by varying structure:
If the components of the composite object and composite object itself support prototype,changing the prototypical components would change the structure of the composite
object, and therefore composite object is changed.
5. Reducing the need for subclassing:
A moment ago, we talked about reducing concrete factory subclassing in Abstract
Factory Pattern, or reducing slightly different subclass into a same class by usingPrototype Pattern. Prototype Pattern can also be used to replace Factory Method Pattern
to create new objects. Hence, the class hierarchy in Factory Method Pattern can be given
up.
6. Configuring an application with classes dynamically:
For dynamically loaded classes, we can only create instances of such classes at run-time.
If the run-time environment creates an instance of each class automatically when it'sloaded, and it registers the instance with a prototype manager. Then the application canask the prototype manager for prototypical instances of newly loaded classes, and clone
the prototypes to create new objects of newly loaded classes.
7. Main liability:Each subclass of Prototype should implement the Clone operation. It's difficult to add
Clone to existing classes. Furthermore, implementing clone can be difficult if the internal
components of the prototype object don't support copying or have circular references.
Implementation
1. Using a prototype manager:When the number of prototypes in a system can be created and destroyed dynamically, a
registry of available prototypes should be kept. The registry is called prototype manager.
The prototype manager is responsible for managing the registered prototypes. Themanaging operations could be: register a prototype under a key, retrieve a prototype with
a given key, unregister a registered prototype, and etc. The clients can use the interface of
prototype manager to store and retrieve prototypes from the registry at run-time.Normally, a client will ask the prototype manager for a prototype before cloning it.
28
http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f9%23f9http://sern.ucalgary.ca/courses/SENG/609.04/W98/hongd/pres2.htm#f9%23f98/8/2019 Design Patterns-Compiled Notes
29/54
2. Implementing the Clone operation.
Deep clone vs. Shallow clone:
A deep clone will clone the instance variables in the cloning object while a shallow clone
share the instance variables between the clone and the original.A shallow clone is simple and often sufficient. But cloning prototypes with complex
structures usually requires deep clone so that the clone and the original are independent.
For a successful deep clone, the components of the clone should be the clones of theprototype's components (i.e. the prototype's components should be clonable).
Circular References:
It's difficult to implement clone if the cloning prototype contains circular references.
3. Initializing clones.
Sometimes, the clone should be initialized by its internal states after it is created. These
values can not be passed to the Clone operation; otherwise the uniform Cloning interfaceof the Clone operation would be destroyed. The initialization can be done either by using
the setting or resetting operations that already existed in the prototype classes or byInitialize operation that takes initialization parameters as arguments and sets and the
clone's internal state accordingly.
Known Uses
ThingLab, users could form a composite object and then promote it to a prototype by
installing it in a library of reusable objects.
Etgdb, a debugger front-end based on ET++ that provides a point-and-click interfaceto different line-oriented debuggers. It looks for a prototype with a specified name ina global table, and then clones the prototype.
The "interaction technique library" in Mode Composer stores prototypes of objects
that support various interaction techniques.
The music editor example mentioned in motivation section is based on the Unidraws
drawing framework.
Sample:
There are various rhythms called taxi, BackYard and Pepper seed. A studio engineer will
voice one of them.
29
8/8/2019 Design Patterns-Compiled Notes
30/54
UML diagram:
Participants:
Abstract Prototype-HotRhythm and ensures that the Concrete-Prototypes implement theICloneable Interface. Also ensures that they have a play method. Since it is an interactinginterface, concrete-products are returned wrapped up in it so as to be unconcerned with
the actual concrete-product at work.
Concrete Prototype -BackYard,PepperSeed, Taxi these are the products which the clientare interested in, which will be used in it operations. Implements the Abstract-Prototype
and hence are able to clone themselves and do the useful work which the client requires.
PrototypeManager-RhythmProtoTypeManagerIn charge of all Prototypes in the
system. Keeps a reference to the available prototypes and implements logic that decides
which prototype to clone and return when requested by the client.
Client StudioEngineerMakes use of the Prototypes. Instantiates Prototype manager andinvokes the factory method on the Prototype manager. This factory method returns the
Prototype which matches the parameter passed to the method.
SAMPLE CODE:
Sample 1:
Abstract Prototype:
public abstract class HotRhytm implements Cloneable{
protected int drumLevel;
protected int bassLevel;
protected int guitarLevel;
30
8/8/2019 Design Patterns-Compiled Notes
31/54
protected String bassLine;
protected String drumTrack;
protected String guitarTrack;
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int getBassLevel() {
return bassLevel;
}
public void setBassLevel(int bassLevel) {
this.bassLevel = bassLevel;
}
public String getBassLine() {
return bassLine;
}
public void setBassLine(String bassLine) {
this.bassLine = bassLine;
}
31
8/8/2019 Design Patterns-Compiled Notes
32/54
public int getDrumLevel() {
return drumLevel;
}
public void setDrumLevel(int drumLevel) {
this.drumLevel = drumLevel;
}
public String getDrumTrack() {
return drumTrack;
}
public void setDrumTrack(String drumTrack) {
this.drumTrack = drumTrack;
}
public int getGuitarLevel() {
return guitarLevel;
}
public void setGuitarLevel(int guitarLevel) {
this.guitarLevel = guitarLevel;
32
8/8/2019 Design Patterns-Compiled Notes
33/54
}
public String getGuitarTrack() {
return guitarTrack;
}
public void setGuitarTrack(String guitarTrack) {
this.guitarTrack = guitarTrack;
}
}
Concrete Prototypes:
PEPPERSEED:
public class PepperSeed extends HotRhytm {
public PepperSeed() {
drumLevel = 5;
bassLevel = 7;
guitarLevel = 4;
bassLine = "Dooo, Doo, dup";
drumTrack = "Dumm, Dumm, Dup, Pish";
guitarTrack = "Ding, Di, Ding, Ding";
}
}
33
8/8/2019 Design Patterns-Compiled Notes
34/54
TAXI:
public class Taxi extends HotRhytm {
public Taxi() {
drumLevel = 6;
bassLevel = 9;
guitarLevel = 4;
bassLine = "Dum, di, Dum, Di, Dumm";
drumTrack = "Dup, Dup, Tick, Dup";
guitarTrack = "Dig, i Dig, Ding, ding";
}
}
BACKAYARD:
public class BackYard extends HotRhytm {
public BackYard() {
drumLevel = 7;
bassLevel = 8;
guitarLevel = 7;
bassLine = "Doo, Dumm, ddooo";
drumTrack = "Dup, Dup, Tick, Dup";
guitarTrack = "Di, Di, Di, Ding";
}
34
8/8/2019 Design Patterns-Compiled Notes
35/54
}
PROTOTYPE MANAGER:
import java.util.Hashtable;
public class RhythmPrototypeManager {
Hashtable rhythmTape = new Hashtable();
BackYard backYardRhythm= new BackYard();
Taxi taxiRhythm= new Taxi();
PepperSeed pepperSeedRhythm= new PepperSeed();
HotRhytm rhythmToMix;
HotRhytm selectedRhythm;
HotRhytm mixRhythmType(String rhythmName){
try {
if(rhythmName.equals("BackYard")){
rhythmTape.put(backYardRhythm,backYardRhythm.clone());
selectedRhythm=
(HotRhytm)rhythmTape.get(backYardRhythm);
}
else if(rhythmName.equals("Taxi")){
rhythmTape.put(taxiRhythm,taxiRhythm.clone());
selectedRhythm=(HotRhytm)rhythmTape.get(taxiRhythm);
}
else if(rhythmName.equals("PepperSeed")){
35
8/8/2019 Design Patterns-Compiled Notes
36/54
rhythmTape.put(pepperSeedRhythm,
pepperSeedRhythm.clone());
selectedRhythm=(HotRhytm)rhythmTape.get(pepperSeedRhythm);
}
rhythmToMix=(HotRhytm)selectedRhythm.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rhythmToMix;
}
}
CLIENT:
public class StudioManager {
public static void main(String[] args) {
RhythmPrototypeManager rhythmSelections= newRhythmPrototypeManager();
HotRhytm rhythmType= rhythmSelections.mixRhythmType("Taxi");
System.out.println("The features of the music voiced are");
System.out.println("Bass level: "+rhythmType.getBassLevel());
System.out.println("Guitarlevel: "+rhythmType.getGuitarLevel());
System.out.println("Drum Level: "+rhythmType.getDrumLevel());
System.out.println("BassLine: "+rhythmType.getBassLine());
System.out.println("Guitar Track: "+rhythmType.getGuitarTrack());
36
8/8/2019 Design Patterns-Compiled Notes
37/54
System.out.println("Drum Track: "+rhythmType.getDrumTrack());
}
}
OUTPUT:
The features of the music voiced areBass level: 9
Guitarlevel: 4
Drum Level: 6BassLine: Dum, di, Dum, Di, Dumm
Guitar Track: Dig, i Dig, Ding, ding
Drum Track: Dup, Dup, Tick, Dup
Sample 2:
package com.apwebco.patterns.gof.prototype;
public abstract class Product implements Cloneable {
private String SKU;private String description;
public Object clone() {Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {e.printStackTrace();
}
return clone;}
public String getDescription() {
return description;}
public String getSKU() {
return SKU;
}
public void setDescription(String string) {description = string;
}public void setSKU(String string) {
SKU = string;
}}
public class Book extends Product {
37
8/8/2019 Design Patterns-Compiled Notes
38/54
private int numberOfPages;
public int getNumberOfPages() {return numberOfPages;
}
public void setNumberOfPages(int i) {numberOfPages = i;
}
}public class DVD extends Product {
private int duration;
public int getDuration() {return duration;
}
public void setDuration(int i) {
duration = i;}
}import java.util.*;
public class ProductCache {
private static Hashtable productMap = new Hashtable();
public static Product getProduct(String productCode) {
Product cachedProduct = (Product) productMap.get(productCode);
return (Product) cachedProduct.clone();}
public static void loadCache() {// for each product run expensive query and instantiate product
// productMap.put(productKey, product);
// for exemplification, we add only two productsBook b1 = new Book();
b1.setDescription("Oliver Twist");
b1.setSKU("B1");
b1.setNumberOfPages(100);productMap.put(b1.getSKU(), b1);
DVD d1 = new DVD();
d1.setDescription("Superman");d1.setSKU("D1");
d1.setDuration(180);
productMap.put(d1.getSKU(), d1);}
}
public class Application {
public static void main(String[] args) {
38
8/8/2019 Design Patterns-Compiled Notes
39/54
ProductCache.loadCache();
Book clonedBook = (Book) ProductCache.getProduct("B1");System.out.println("SKU = " + clonedBook.getSKU());
System.out.println("SKU = " + clonedBook.getDescription());
System.out.println("SKU = " + clonedBook.getNumberOfPages());
DVD clonedDVD = (DVD) ProductCache.getProduct("D1");
System.out.println("SKU = " + clonedDVD.getSKU());System.out.println("SKU = " + clonedDVD.getDescription());
System.out.println("SKU = " + clonedDVD.getDuration());
}
}
Variations in prototype:
1a.Personal-Prototype Only one client references the prototype each time the program
runs, but changes it. In this case deep copying is a waste since changes to the prototype
do not affect other clients.
1b.NewsMedia-Prototype The prototype is never modified but several clients may
reference it. If this is guaranteed to be the case, then you should probably make theproperties read-only. This ensures that there is no "rogue-state object" to violate the
agreements set down by the community.
1c.Environmental-Prototype The prototype is accessed and modified by several clients,each client is interested in the changes made by other clients. The prototype should
clearly be read/write but deep copying should not be done. Since the prototype is
automatically implemented as a singleton, returning a shallow copy ensures that changesmade by one client are seen by subsequent clients. In this particular instance deep
copying is actually dangerous since it would allow several instances to exist which mayor may not have the latest changes. This is equivalent to losing uncommitted changes ina database because someone else read the same record you have in memory, but made
and saved changes which were committed after you committed your changes. Of course
modern databases are not susceptible to snafus such as this, but you get the picture.
1d.Evolution-Prototype Changes made to the prototype should be persisted so that
future program executions use the updates. In order to persist the changes so future
program executions do not start building the concrete-prototypes from scratch andoverhauling the prototype each time, you will need to persist the object state by saving
the state to a database or XML. Each time the program runs and instantiates a Prototype,
it does so by reading back the most current data from the database or XML file. Thebuilder pattern would possibly be useful in helping to re-create prototype each time
before its actual use.
39
8/8/2019 Design Patterns-Compiled Notes
40/54
Builder Pattern
Intent:
Separate the construction of a complex object from its representation so that the same
construction process can create different representations.
Intent seen through real life:
Let's say you are baking a cake from a cake mix. The basic steps which are involved increating a cake from the cake mix are more or less fixed. You have the possibility of
swapping several components based on availability, cost or health reasons. At the end
you are still baking a cake so the representation of the product which results changes, but
the baking (construction) process is relatively stable.So the "cake mix baking process" is a fairly adaptable process which can be suited to a
variety of types of cakes and in this respect it reflects the builder pattern.
The idea behind the builder pattern is to create a complex or multipart object on behalf of
a client who knows what object is being created but does not know how it is being put
together. It is applicable when an object cannot be created in an arbitrary manner. It helpsthe construction process to meet these requirements:
There are several steps used to create the parts which make up the complex
object.
These steps need to be carried out in a particular sequence.
The product instantiation process must be hidden from the client.
The pattern advocates the association of one instantiator-class for each of the
representations of the product which may be created. All the steps for creating theproduct class are written into the instantiator-class which is responsible for creating it.
Lets look at the other two issues in a bit depth:
Firstly we need to ensure that all the steps in the product instantiation sequence arecarried out. In the real life example we can use butter and flour or we can use grease
paper to line our pan, but if we skip this step we end up with a cake which cannot be
removed from the tin. We can use an electric mixer or hand mixer to mix our ingredientsbut if we skip the mixing we end up with a cake which is very inconsistent: soppy in
some parts and dry in others. If we don't add eggs or some similar moistening agent, then
our cake doesn't pass the fork test. So the steps themselves are important and we cansubstitute components (egg for milk) and we can substitute methods (electric mixer for
Hand mixer) but we cannot skip any step.
Secondly, we need to ensure that the steps are carried out in a particular order. If we mix
the ingredients before adding water, the mixing will not be as effective. If we put the cakein the oven for 45 minutes, take it out and then set the temperature to 350 degrees, we end
40
8/8/2019 Design Patterns-Compiled Notes
41/54
up with an unbaked cake and . So the order of the steps is also important.
So we must follow all steps and in the required order. The builder pattern allows us to
ensure that the two criteria are achieved while allowing us the flexibility to substitute
methods and ingredients which suit our particular cake being baked. It achieves this byimposing a recipe approach to composing the complex object. It does this in two parts.
Components of the builder approach:
1. AbstractBuilder: It is represented by the general cake baker who knows all the stepswhich are needed for composing the complex object. Because all our specialist cake
bakers are familiar with the steps needed for cake baking, it ensures that there is expertise
in all the steps to be executed. The GeneralCakeBaker interviews all specialist bakersbefore they can be employed in the bakery. She ensures that the SpecialistCakeBaker is
expert in all the steps which are specific to the kind of cake they are supposed to be
baking. Later you will understand why, but for now, accept that the specialist bakers must
know all the steps in bold-italic[/italic] (they are abstract steps) but not necessarily thesteps in bold (they are concrete steps), since she already knows those general steps. Note
also that some of the steps are already filled in. Also, in our cake baking example, theorder is not important. In fact it is an unordered list, looking something like:
GeneralCakeBaker (AbstractBuilder)
Add_MoisteningAgent:[/italic]
Bake contents: Pour contents into tin. Set timer for 45 minutes, place tin in oven
and remove when timer sounds. Turn off oven.
Mix till consistent:[/italic]
Grease pan:[/italic]
Set oven temperature: Turn knob to 375 degrees
Pour in CakeMix:[/italic]
2. ConcreteBuilder: Each type of product (cake) which can be created is tied to one
specialist baker. He knows how to carry out each of the steps in the general recipe for the
particular type of cake he bakes and so we can consider him to be an extension of theGeneralCakeBaker. However each baker can bake only the type of cake which he
specializes in. So we may have the ChocolateCakeBaker, OrangeCakeBaker,
FruitCakeBaker etc. Only the ChocolateCakeBaker can make ChocolateCake and theOrangeCakeBaker must know how to carry out all the steps which apply to the baking of
an Orange cake. In reality he only needs to know the steps which are indicated in bold-italics[/italic]. The other steps which are in bold are considered general steps, do not need
specialization and so will be taken care of by the GeneralCakeBaker herself. Thespecialist cake baker can override the Master baker however and so the Chocolate cake
baker can bake his cake for less time at a higher temperature if so desired. Since
knowledge of the steps must reflect all the steps as outlined by the GeneralCakeBaker, itensures that the SpecialistCakeBaker is in a position to do all the steps. The great thing
though is that we can customize the cake we make by changing the SpecialistCakeBaker
we use to bake it. Because all specialists know the steps relevant to their cake, it ensuresour cake is baked completely. Each specific cake baker in our example reflects the role of
41
8/8/2019 Design Patterns-Compiled Notes
42/54
the concrete-builder in the Builder pattern. Note very importantly, that in ourexample, the specialist cake bakers do not know the order in which the steps are
carried out. As we will see, the MasterCakeBaker knows the order of the steps and
will take care of the sequencing requirement.
3. Director: The Director in the pattern is represented by our MasterCakeBaker. Thedirector ensures that the steps are executed in the right order. In our case the director, an
experienced baker, knows the order in which the steps must be executed in order to
ensure that the cake is baked properly and orders the specialist cake baker to carry outeach step in turn. So he may call the specialistCakeBaker and tell him to get going, then
call out the following instructions which the specialist must execute in the following
order. (ITSB stands for - Instruction To Specialist Baker).
a. ITSB: "Grease pan"b. ITSB: "Set oven temperature"
c. ITSB: "Pour in CakeMix"
d. ITSB: "Add_MoisteningAgent"
e. ITSB: "Mix till consistent"f. ITSB: "Bake contents
Note something very important here though. The MasterCakeBaker has a communication
problem and only gets along with people he has known for a long time. Worse yet, the
specialist cake bakers and premadonnas and are themselves difficult to get along with. So
we shield the MasterCakeBaker from the flightiness of the SpecialistCakeBakers and heonly deals with the GeneralCakeBaker who has been around since the bakery started. So
in reality, he speaks to the SpecialistCakeBaker through the GeneralCakeBaker. He never
knows the specialistCakeBaker on duty and doesn't care. Now the GeneralCakerBakerimplements the step that she can, but passes on the specialized steps to the Specialist. Inso doing, we get our cake baked, but without any direct contact between the
MasterCakeBaker (Director) and SpecialistCakeBakers (Abstract Builder). This isjust as well because they are easily offended and the fact that the MasterCakeBaker
cannot remember their names is very offensive to each of them.
4. ConcreteProduct: The complex object in our example is the cake and it reflects the
role of the concrete product in the builder pattern. Remember each concrete product is
built by only one builder. In fact selecting the builder is in effect, selecting the product.
So when we select the OrangeCakeBaker, we are guaranteed to get back an Orange cake.
5. Client: The client in the pattern is similar to the customer of the bakery. In the case of
the customer, an order for a particular type of cake (or concrete product) is made. Thecustomer hopes that the cake will taste a bit better than concrete and that biting into it
will not require a trip to the dentist. But the other similarities are true. The only difference
is that the client in the pattern knows all about the available products and knows whichconcrete-builder is responsible for each product. In fact the customers come here because
they know that the bakery has been on a drive to get all the best specialist bakers in one
place and the customers even know the names of the specialistBakers who work for the
bakery and the type of specialty cake that they bake.
42
8/8/2019 Design Patterns-Compiled Notes
43/54
Let's put it all together. In the bakery, the customer walks in and asks the
GeneralCakeBaker to call Oraine the OrangeCakeBaker to bake her a cake. She has heardabout the fantastic cake he bakes. The GeneralCakeBaker walks into the
MasterCakeBakers office and say "Boss, we have an order". The MasterCakeBaker
washes his hands and starts to shout instructions to the GeneralCakeBaker. TheGeneralCakeBaker knows how to do the general steps and takes care of them, but the
other steps she delegates to the SpecialistCakeBaker. The MasterCakeBaker puts the
icing on the cake and grabs credit for baking (how do you think he got to beMasterBaker) by returning the cake to the client, who thanks him very much.
The client-code knows which concrete-product it requires at any point in time. It also
knows which concrete-builder is able to return that concrete-product. It thereforeinstantiates the required concrete-builder posing as the abstract-builder. The concrete
builder has a reference to a concrete product which is automatically instantiated as well.
The client code also instantiates the director with a reference to the concrete-builder
(wrapped in the abstract-builder's interacting-interface) which it needs to make aparticular product. The client then calls the construct method on the director which in
turn invokes the methods of the concrete-builder (which it aggregates), in the sequencerequired. The Director finally returns the concrete-product to the client.
UML Diagram:
Some advantages of using the builder pattern are as follow:
43
8/8/2019 Design Patterns-Compiled Notes
44/54
The object oriented requirement of encapsulation is used to hide the creation of
complex objects behind an interface.
The characterizing features of an object can be changed without changing themanner in which the object is created.
Two disadvantages of the builder pattern are
By using multiple classes and many methods this process of creation may create
additional overhead compared to an instance by instance creation method.
More initial programming work to separate code to work under this approach.
Example:
Prepare a Pizza of the customers choice by changing the dough, topping and sauce for
each pizza.
AbstractBuilder: PizzaBuilder.java
public abstract class PizzaBuilder {Pizza pizza = new Pizza();
public Pizza getPizza(){
return pizza;
}public static PizzaBuilder getBuilder(PizzaBuilder pizzaBuilder){
return pizzaBuilder;
}public void buildDough(){
pizza.setDough("Pizza Base");
}
public abstract void buildSauce();public abstract void buildTopping();
}
Concrete Builders:
HawaainPizzaBuilder.java
public class HawaainPizzaBuilder extends PizzaBuilder {
public void buildSauce() {
pizza.setSauce("mild");}
public void buildTopping() {pizza.setTopping("pineapple + ham");
}
}
44
8/8/2019 Design Patterns-Compiled Notes
45/54
SpicyPizzaBuilder.java:
public class SpicyPizzaBuilder extends PizzaBuilder {
public void buildSauce() {pizza.setSauce("chilly");
}
public void buildTopping() {
pizza.setTopping("pepper+salami");
}
}
Product: Pizza.java
public class Pizza {
private String dough="";
private String sauce="";private String topping="";
public void setDough(String dough) {this.dough = dough;
}
public void setSauce(String sauce) {
this.sauce = sauce;}
public void setTopping(String topping) {
this.topping = topping;}
public String getDough() {
return dough;}
public String getSauce() {
return sauce;}
public String getTopping() {
return topping;
}
}
45
8/8/2019 Design Patterns-Compiled Notes
46/54
Director: Waiter.java
public class Waiter {
private PizzaBuilder pizzaBuilder;
public Pizza constructPizza(String pizzaBuilderName, PizzaBuilderpizzaBuilderType)
{
pizzaBuilder=PizzaBuilder.getBuilder(pizzaBuilderType);
pizzaBuilder.buildDough();pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
return pizzaBuilder.getPizza();
}
}
Client :Customer.java
import java.io.BufferedReader;import java.io.IOException;
import java.io.InputStreamReader;
public class Customer {
public static void main(String[] args) {
Waiter waiter = new Waiter();PizzaBuilder pizzaBuilder=null;
System.out.println("Enter the choice of pizza : HawaainPizza or
SpicyPizza ");System.out.println("(Enter the choice as displayed here)");
String product="";
BufferedReader br = new BufferedReader( new
InputStreamReader(System.in));try {
product=br.readLine();
} catch (IOException e) {// TODO Auto-generated catch block
e.printStackTrace();
}if(product.equalsIgnoreCase("HawaainPizza")){
pizzaBuilder=new HawaainPizzaBuilder();
}
else{
46
8/8/2019 Design Patterns-Compiled Notes
47/54
pizzaBuilder= new SpicyPizzaBuilder();
}
Pizza pizza=waiter.constructPizza(product,pizzaBuilder);System.out.println("Your pizza is made of: "+ pizza.getDough()
+" ,"+pizza.getSauce()+" sauce and "+pizza.getTopping()+" topping");
}}
47
8/8/2019 Design Patterns-Compiled Notes
48/54
Behavioral Patterns
Introduction:
Behavioral patterns are concerned with algorithms and the assignment of responsibilities
between objects. They describe not just the patterns of objects or classes but also thepattern of communication between them. They characterize complex control flow thats
difficult to follow at run time.
Behavioral class patterns use inheritance to distribute behavior between classes.There are two such patterns: Template pattern and the Interpreter pattern. Behavioral
object patterns use object composition rather than inheritance. Some of these patterns
describe how a group of peer objects cooperate with each other to perform a task that
cannot be performed by a single object. The others are concerned with encapsulating thebehavior in an object and delegating requests to it.
1. CHAIN OF RESPONSIBILITY PATTERN:
Chain of responsibility allows decoupling between objects by passing a request from oneobject to the next in a chain until the request is recognized. It lets us to send the requests
to an object implicitly through a chain of objects. Any candidate may fulfill the request
depending upon the run-time conditions. The number of candidates is open-ended, and
thus we can select which candidates participate in the chain at run-time.It consists of a source of command objects and a series of processing objects.
Each processing object contains a set of logic that describes the types of command
objects it can handle, and how to pass off those that it cannot handle to the nextprocessing object.
Intent:Avoid coupling the sender of a request to its receiver by giving more than one object a
chance to handle the request. Chain the receiving objects and pass the request along the
chain until an object handles it.
Motivation:
Consider a context-sensitive help facility for a graphical user interface. The user can
obtain help information on any part of the interface just by clicking on it. The help that'sprovided depends on the part of the interface that's selected and its context; for example,
a button widget in a dialog box might have different help information than a similar
button in the main window. If no specific help information exists for that part of theinterface, then the help system should display a more general help message about the
immediate contextthe dialog box as a whole, for example.
Hence it's natural to organize help information according to its generalityfrom the mostspecific to the most general. Further more, it's clear that a help request is handled by one
of several user interface objects; which one depends on the context and how specific the
available help is. The problem here is that the object that ultimatelyprovides the help isn't
known explicitly to the object (e.g., the button) that initiates the help request. What we
48
8/8/2019 Design Patterns-Compiled Notes
49/54
need is a way to decouple the button that initiates the help request from the objects that
might provide help information. The Chain of Responsibility pattern defines show that
happens. The idea of this pattern is to decouple senders and receivers by giving multipleobjects a chance to handle a request. The request gets passed along a chain of objects
until one of them handles it. The first object in the chain receives the request and either
handles it or forwards it to the next candidate on the chain, which does like wise. Theobject that made the request has no explicit knowledge of who will handle itwe say the
request has an implicit receiver.
Let's assume the user clicks for help on a button widget marked "Print." The button is
contained in an instance of PrintDialog, which knows the application object it belongs to(see preceding object diagram).The following interaction diagram illustrates how the help
request gets forwarded along the chain:
In this case, neither aPrintButton nor aPrintDialog handles the request; it stops at an
Application, which can handle it or ignore it. The client that issued the request has nodirect reference to the object that ultimately fulfills it. To forward the request along the
chain, and to ensure receivers remain implicit, each object on the chain shares a commoninterface for handling requests and for accessing its successor on the chain. For example,the help system might define a HelpHandler class with a corresponding HandleHelp
operation. HelpHandler can be the parent class for candidate object classes, or it can be
defined as a mixin class. Then classes that want to handle help requests can make
HelpHandler a parent: The Button, Dialog, and Application classes use HelpHandleroperations to handle help requests. HelpHandler's HandleHelp operation forwards the
request to the successor by default. Subclasses can override this operation to provide help
49
8/8/2019 Design Patterns-Compiled Notes
50/54
under the right circumstances; otherwise they can use the default implementation to
forward the request.
Applicability:
The chain of responsibility pattern can be used when
More than one object may handle a request, and the handler is not known .The
handler should be ascertained automatically.
A request has to be issued to one of the several objects without specifying thereceiver explicitly.
The set of objects can handle a request should be specified dynamically.
Structure:
50
8/8/2019 Design Patterns-Compiled Notes
51/54
A typical object structure might look like this:
Participants:
1. Handler: (HelpHandler)
It defines an interface for handling the requests.
It might implement the successor link.
2. ConcreteHandler: (PrintButton, PrintDialog)
Handles the request it is responsible for.
Can access its successor
If it can handle the request, it does so. Otherwise it forwards the request to its
successor.
3. Client:
Initiates the request to a ConcreteHandler object on the chain.
Collaborations:
When a client issues a request, the request propagates along the chain until a
ConcreteHandler object takes the responsibility for handling it.
Consequences:
1. Reduced coupling:
The pattern frees an object from knowing which other object handles the request. Anobject has to know only that a request will be handled appropriately. The receiver and
sender do not have an explicit knowledge about each other. An object in the chain need
not know the structure of the chain. Instead of maintaining references to all thecandidates, the objects maintain only a single reference to their successor.
2. Added flexibility in assigning responsibilities to objects:
New responsibilities can be added or the existing responsibility for handling a request can be changed by adding a handler to the chain or changing the chain at run time.
Subclassing can also be combined to specialize handlers statically.
3. Receipt is not guaranteed:
Since a request has no explicit receiver, there is no guarantee that it will be handled. The
request can fall off the end of the chain without ever being handled. A request can also gounhandled if the chain is not configured properly.
Implementation:
1. Implementing the successor chain.
There are two possible ways to implement the successor chain:a. Define new links (usually in the Handler, but ConcreteHandler should define them
instead).
51
8/8/2019 Design Patterns-Compiled Notes
52/54
b. Use existing links.
Our examples so far define new links, but often you can use existing