design patterns iii - creatonal design...
TRANSCRIPT
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.1
Design Patterns • IIICreatonal Design Patterns
COMP2110/2510Software DesignSoftware Design for SESeptember 12, 2008
Alexei Khorev
Department of Computer Science
The Australian National University
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.2
1 Creational Patterns
2 Factory Method
3 Abstract Factory
4 Singleton
5 Monostate
6 Other Creational Patterns
Builder
Prototype Pattern
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.3
Creational Design Patterns
Creational Patterns of GoF
• Abstract Factory
• Factory Method
• Builder
• Prototype
• Singleton
Creational DPs are abstraction of the instantiation process. Their
common purpose to make a system independent of how its
objects are created, put together and represented. The patterns
can have either the class scope (eg, F M) — they use
inheritance to vary the class which instantiated, or object scope(eg, A F) — in which the instantiation task is
delegated to another object.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.4
Factory Method Pattern, Problem
Intent : Define an interface for creating an object, but let
subclasses decide which class to instantiate. Factory Method lets
a class defer instantiation to subclasses.
This pattern helps to avoid violation of one of the OO design
principle: “Program to an interface, not an implementation”,
when a client class must create objects which are instances of
volatile classes. If your code depends (uses) a concrete class, and
it is not a stable API class like String and is subject to change, the
dependency makes likely future changes in the class
implementation problematic.Here, SomeApp depends on the interface
Shape — good! since it does not use the
subclass (Square, Circle) specific meth-
ods, but if SomeApp creates instances of
Square or Circle, it therefore depends on
the concrete classes (bad!).
To fix this problem the direct call of the
subclass constructors by SomeApp should
be replaced by using factory methods de-
fined in the ShapeFactory interface with the
methods to return a newly created object of
the required class.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.5
Factory Method Pattern, Solution
ShapeFactory.java
public interface ShapeFactory {public Shape makeCircle();public Shape makeSquare();
}
ShapeFactoryImpl.java
public class ShapeFactoryImplimplements ShapeFactory {
public Shape makeCircle() {return new Circle();}
public Shape makeSquare() {return new Square();}
}
The client SomeApp now has no concrete class dependency, yet it
can still create any of them. Those instances are manipulated via
the Shape interface, and never with methods specific to the
concrete subclasses.
In a real application, someone (the main method or an initialization
method inside main) will have to create ShapeFactoryImplconcrete factory class, but nobody will need to invoke the Squareand Circle constructors.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.6
Factory Method Pattern, Formal Structure
Participants
• Product — defines the interface of objects the factory method creates
• ConcreteProduct — implements the Product interface
• Creator —
◦ declares the factory method, which returns an object of type Product. Creator may
also define a default implementation of the factory method that returns a default
ConcreteProduct object
◦ may call the factory method to create a Product object
• ConcreteCreator — overrides (implements) the factory method to return an instance of
a ConcreteProduct
Collaborators
• Creator relies on its subclasses to define the factory method so that it returns an
instance of the appropriate ConcreteProduct
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.7
Factory Method Pattern, Consequences
Factory methods eliminate the need to bind application-specific classes
into your code. The code only deals with the Product interface; therefore
it can work with any user-defined ConcreteProduct classes.
A potential disadvantage of factory methods is that clients might have to
subclass the Creator class just to create a particular ConcreteProductobject. Subclassing is fine when the client has to subclass the Creatorclass anyway, but otherwise the client now must deal with another point of
evolution.
Namely, the class ShapeFactory has a method for every subclass of
Shape, which results in a dependency cycle: adding new subclasses to
Shape is problematic — every time we also have to add a new method to
ShapeFactory interface (normally, a recompilation of all users of
ShapeFactory is necessary). The way to overcome this dependency cycle
may involve a generic method, use of reflections, or a complicated (and
error-prone) logic for ShapeFactoryImpl method which will select the right
subclass constructor. Each way has its trade-offs.
To summarize: Use the Factory Method pattern if
• A class can not anticipate the class of objects it must create
• A class wants its subclasses to specify the objects it creates
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.8
Abstract Factory Pattern
Intent : Provide an interface for creating families of related or
dependent objects without specifying their concrete classes.
The Abstract Factory is similar to the Factory Method. The differences:
• In the Abstract Factory pattern, a class delegates the responsibility
of object instantiation to another object via composition whereas the
Factory pattern uses inheritance and relies on a subclass to handle
the desired object instantiation
• The delegated object of the Abstract Factory frequently uses factory
method to perform the instantiation
Use the pattern if:
• A system should be independent of how its products are created,
composed and represented
• A system should be configured with one of multiple families of
products
• A family of related product objects is designed to be used together,
and you need to enforce this constraint
• You want to provide a class library of products, and you want to
reveal just their interfaces, not their implementation
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.9
Abstract Factory Pattern, Example
A software system for handling student results has these requirements:
• There are two classes of students: Arts and Science. Each Faculty will have its own set
of records, one for all Arts students, the other for all Science students.
• A student’s record contains an ID number, type of degree, and marks for all subjects
taken this semester.
• Arts students’ records have their major discipline (a string like “History”).
• Arts students only take Arts subjects; Science students only take Science subjects.
• Each arts student takes 4 subjects, each science student takes only 3.
• Every subject has a name and a subject code.
• Arts subjects have an exam mark and an essay mark, each out of 100.
• Science subjects have an exam mark out of 100 and two assignment marks.
• Every subject has a final mark that can be computed by a function called final.
• The same method called grade is used for all subjects for calculating the grade from the
final mark.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.10
Abstract Factory Pattern, Example (concl.)RM = new ArtsRecordMaker(); // or new ScienceRecordMaker();s = RM.CreateStudent(); //includesset of NSubjs subjectsfor i in [1..s.NSubjs]s.subjects[i]= RM.CreateSubject();
Client App
ArtSubject ScienceSubject
Subject
exam examessay ass1
ass2final() final()
Student
ArtStudent ScienceStudent
Id, Degree
AbsRecordMaker
ScienceRecordMaker
CreateStudent()
CreateStudent()CreateSubject()
CreateSubject()
ArtRecordMaker
CreateStudent()CreateSubject()
final()
grade()
grade()
grade()
<<
create>>
<<create>> <<
crea
te>
>
<<create>>
AbstractFactory
ProductA2ProductA1
AbstractProductA
ProductB1 ProductB2
AbstractProductB
ConcreteFactory1 ConcreteFactory2
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.11
Abstract Factory Pattern, Formal Structure
Participants
• AbstractFactory — declares an interface for operations that create abstract product
objects
• ConcreteFactory — implements the operations to create concrete product objects
• AbstractProduct — declares an interface for a type of product object
• ConcreteProduct —
◦ defines a product object to be created by the corresponding concrete factory
◦ implements the AbstractProduct interface
• Client — uses only interfaces declared by AbstractFactory and AbstractProduct classes
Collaborators
• A single instance of a ConcreteFactory class is created at run-time. This concrete
factory creates product objects having a particular implementation. To create different
product objects, clients should use a different concrete factory
• AbstractFactory defers creation of product objects to its ConcreteFactory subclass
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.12
Abstract Factory Pattern, Consequences
Advantages
• It isolates concrete classes — the pattern helps you control the
classes of objects that an application creates. Because a factory
encapsulates the responsibility and the process of creating product
objects, it isolates clients from implementation classes. Clients
manipulate instances through their abstract interfaces. Product class
names are isolated in the implementation of the concrete factory;
they do not appear in client code.
• It makes exchanging product families easy — since the class of a
concrete factory appears only once in an application.
• It promotes consistency among products — since the application is
using objects from only one family at a time.
Disdvantages
• Supporting new kinds of products is difficult — the pattern interface
fixes the set of products that can be created. Supporting new kinds
of products requires extending the factory interface, which involves
changing the AbstractFactory class and all of its subclasses (again,
a dependency cycle).
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.13
Singleton Pattern
Intent: Ensure a class only has one instance, and provide a global
point of access to it.
Normally, a class has multiple instances: a client can create as many as
needed and delete them when they are no longer required (or reply on the
garbage collector to clean up). But there are classes which should have
only one instance at most which comes into existence when the program
starts and is disposed when the program ends. It is useful or even
important when exactly one object coordinates actions across the system.
Examples:
• One file system
• One window manager or the tool palette
• One factory to create other objects (eg, in Abstract Factory)
• One object or threads manager
If more than one object of such kind is created, the complexity of the
application logic and chance of its failure are substantially higher: eg, if
more than one object factory exists the control over the created objects
may be compromised. For multiple task managers, activities may become
concurrent etc.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.14
Singleton Pattern, Formal Structure
Use the pattern if:
• there must be exactly one instance of a class, and it must be
accessible to clients from a well-known access point
• when the sole instance should be extensible by subclassing,
and clients should be able to use an extended instance
without modifying their code
Participants
• Singleton —
◦ defines a Instance() method that lets clients access its unique
instance. Instance() method has a class scope
◦ may be responsible for creating its own unique instance (static in
Java)
Collaborators
• Clients access a Singleton instance solely through its Instance()method
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.15
Singleton Pattern, Implementation
public class Singleton {
private static Singleton inst = null;private Singleton() { ... }
public static Singleton Instance() {if (inst == null)inst = new Singleton();
return inst;}
}
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.16
Singleton Pattern, Consequences
Advantages
• Cross platform — can be extended to work accross many JVM’s and
many computers
• Applicable for any class — any class can be made a Singleton by
simple code modification (make its constructors private and add
necessary static methods and fields)
• Permits refinement of operations and representation — a class may
be subclassed to a Singleton
• Lazy evaluation — if never used, it’s never created
Disdvantages
• Destruction undefined — removing a Singleton object can be a
subtle problem
• Concurrency — in a multi-threaded application, care is needed to
avoid re-creation of a Singleton object by different threads
• Not inherited — Singleton’s child is not automatically a Singleton
• Efficiency — most of the if’s are useless
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.17
Variation on Singleton: Monostate?
What if we need the class whose objects have the behaviour of
S without constraint of a single instance? If the different
instances have always the same behaviour, this can be achieved
by making the fields of the objects (which determine the object
state) be always the same, ie, by declaring the fields static.
public class Monostate {
private static int itsX = 0;public Monostate() { ... }
public void setX(int x) {itsX = x;
}public int getX() {return itsX;
}}
We can create as many Monostateinstances as we like — they all will
behave as they were a single ob-
ject. The Monostate objects can be
destroyed (all of them!), and without
loss of data (static!!).
Exercise: write down — first! — the JUnit test for a Singleton class, and then run until it
passes. Then replace The Singleton objects with Monostate objects and convince that the
tests pass too.
? This pattern has been suggested by S. Ball & J. Crowford. The detailed reference and discussion can be found in R. Martin’s book
“Agile Software Development”, Prentice Hall, 2003
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.18
Singleton vs Monostate
The difference between S and M is behaviour
versus structure. The S pattern enforces the singular
structure — the number of instances cannot exceed one. The
M pattern provides the singular behaviour — no constraint
on the number of instances.
Advantages
• Transparency — clients of Monostate do not have to know that the object they use is
Monostate, it’s just an ordinary class
• Inheritance — subclasses of Monostate are Monostates too
• Polymorphism — the Monostate methods arn’t static, the can be overridden, so the
subclasses can be used to get different behaviour over the same class fields
Disdvantages
• No conversion — A normal class cannot be subclassed to Monostate
• Efficiency — A Monostate can go through multiple creations (costly operation)
• Presence — The Monostate fields take up space even if the instances never used
• Locality — The Monostate objets don’t work across several JVMs or several platforms
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.19
Builder Pattern
Intent: Separate the construction of a complex object from its
representation so that the same construction process can create
different representations.
A F is similar to B in that it too may construct
complex objects. The primary difference is that the B pattern
focuses on constructing a complex object step by step. AF’s emphasis is on families of product objects (either simple
or complex). B returns the product as a final step, but as far
as the A F pattern is concerned, the product gets
returned immediately.
Use the pattern if:
• the algorithm for creating a complex object should be independent of
the parts that make up the object and how they’re assembled (this is
different from A F)
• the construction process must allow different representations for the
object that is constructed
Note: the Oops program (used in COMP2100) has not been designed without the B DP
in mind, though it does fit the pattern intent (when creating plain text, html, or GUI output by
reading the XML-document parse tree). It would be a worthy exercise to refactor the Oopscode to utilize B.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.20
Builder Pattern, The diagrams
The B dynamics
• The client creates the Directorobject and configures it with
the desired Builder object
• Director notifies the builder
whenever a part of the product
should be built
• Builder handles requests from
the director and adds parts to
the product
• The client retrieves the product
from the builder
A Composite (parse and document trees) is what the builder often builds.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.21
Prototype Pattern
Intent: Specify the kinds of objects to create using a prototypical
instance, and create new objects by copying this prototype.
Difference from F MBoth F M and P are able to create objects that fit a given interface. But while
in F M each factory is defined by subclassing to define the choice of particular
objects created by the factory, in P each concrete prototype is defined by a set of
original objects (not classes) and creates by copying from a selected original. The decision to
choose the subclass objects — or even to choose the subset of objects defined by their value,
which may not be defined by separate subclasses — to be deferred to runtime.
Use the pattern if a system should be independent of how its products
are created, composed, and represented, and
• when the classes to instantiate are specified at run-time, or
• you have to avoid building a class hierarchy of factories that parallels
the class hierarchy of products, or
• when instances of a class can have one of only a few different
combinations of state. It may be more convenient to install a
corresponding number of prototypes and clone them rather than
instantiating the class manually, each time with the appropriate state
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.22
Prototype Pattern, Structure
Participants
• Prototype — declares an interface for cloning itself
• ConcretePrototype — implements an operation for cloning itself
• Client — creates a new object by asking a prototype to clone itself
Collaborators
• a client asks a prototype to clone itself
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.23
Prototype Pattern, Benefits
Benefits
• Objects (products) can be added and removed at run-time
• New behaviour can be defined without creating new classes, but
through object’s composition. The number of classes which the
system needs can be greatly reduced
• Solves the F M’s problem of the Creator subclass
proliferation (when the Product hierarchy grows)
• The ability to configure an application with classes dynamically
Cloning is the main assumption and liability of P.
Calling a constructor creates a new object in a specified (pristine) state which is determined by
the constructor definition (and the language rules). If the task is to create an identical copy of
an object which is in the very same state as the original at the moment when the copy is
needed, then the clone() operation is needed Some languages have the cloning support at
the basic level (Eiffel has the deep clone() routine for every object; Java lacks the elemental
language support, instead relying on a rather artificial construct which involves Cloneableinterface from its API — the writer of a new class must himself consider whether to implement
or not the clone() method, and how to do it —
• shallow clone, or
• deep clone
The cloning is the basis of P DP, but the clone() operation in itself is not P(otherwise it wouldn’t be a design pattern). The P DP decouples clients from the actual
product (ConcretePrototypes) classes through the Prototype interface. The ConcretePrototypeclasses are thus hidden from the client, and the latter can be re-configure or changed.
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.24
Prototype Pattern, Example
A similar example is discussed in Fox, p. 563
Architecture Editor (a structured drawing tool)
Many drawing editors have the facility for the user to use
a set of libraries that contain composite objects. The GoF
example has musical notations.
• GraphicTool classes are written to generate the drawing of an item on screen
• GraphicTool is written in the Graphics framework, but musical notes etc. are in one
application, circuit elements in another application, UML diagram fragments in yet
another, or in different libraries, picked up by one of the applications. We need to be
able to extend the GraphicTool to new application areas easily (reuse!).
• A new subclass for every graphic element would be possible — but a lot of small very
similar classes to write — many have the same properties, just a different bitmap image
etc. and no other attributes apart from position, scale, colour — all in common
• If the user can create and save a library of objects (extend or build a new library) then
making new subclass for each object is not necessary
• Dynamic objects are often preferred over static classes: for example the dia tool
generalises all of its graphics by reading descriptions from a user-editable text format file
(UML elements, SADT elements, Circuits, Flowcharts, ER diagrams. . . )
Design Patterns • III
Alexei Khorev
Creational Patterns
Factory Method
Abstract Factory
Singleton
Monostate
Other Patterns
Builder
Prototype
17.25
Abstract Factory, Builder and Prototype (cited from GoF)
All three are about parameterizing a system by the classes of objects
which the system creates: they define an object that is responsible for
knowing the class of the product objects, and make it a parameter of the
system. The details are different:
• A F has the factory object producing objects of several
classes
• B has the factory object building a complex product
incrementally using a correspondingly complex protocol
• P has the factory object building a product by copying a
prototype object (the factory object and the prototype are the same
object, since the prototype returns the product)
“Which pattern is best depends on many factors. In the previous example (GraphicsTool) the
P is the best choice because it only requires implementing a clone() operation on
each Graphics class. That reduces the number of classes, and clone() can be used for
purposes other than pure instantiation (eg, a duplicate_menu() operation).
Designs that use A F, P, or B are even more flexible than those that
use F M, but they are also more complex. Often, designs start out using FM and evolve toward the other creational patterns as the designer discovers where more
flexibility is needed. Knowing many design patterns gives you more choices when trading off
one design criterion against another.”