Title: Creational Design Patterns
1Creational Design Patterns
Factory Method Abstract Factory Builder Prototype
Singleton Object Pool
2CDP - Factory Method
Synopsis Need for a class for reuse with
arbitrary data types. Reusable class remains
independent of the classes it instantiates by
delegating the choice of which class to
instantiate to another object and referring to
the newly created object through a common
interface. Context Creates a framework to
support instantiations of various data types.
3CDP - Factory Method
Forces Provide services (methods) in a way
transparent to classes using those services.
Solution Proxy object and the service
providing object must either be instances of a
common super class or implement a common
interface. Consequences Could introduce new
failure points.
4CDP - Factory Method - Example
You have an application such as MS Office. You
want to perform some common functions with all
the files. Example of common functions might be
open file, save file, etc. The only difference is
that the functions are done on different file
types such as word doc files, excel xls files and
PowerPoint ppt files. You could write several
independent functions for each of the different
types but the code would be very similar with
only the data type as a difference. The
factory method allows you to build a framework to
perform the common functions with only a few
classes that reused for each type.
5CDP - Factory Method - Example
Manage Doc Files
doc file commands
Manage Xls Files
xls file commands
Manage Ppt Files
ppt file commands
file commands
Manage Files
Make one Function
6CDP - Factory Method - Example
edits
Document
Application
1
MyDocument
May be doc, xls, or ppt.
7CDP - Factory Method - Example
edits
Document
Application
1
Requests creation
creates
DocumentFactoryIF
MyDocument
DocumentFactory
8CDP - Factory Method - Example
Suppose you have a process which reads and
writes a DataStream to a socket.
Write to Socket
stream
Socket
string
Read from Socket
stream
Socket
string
But you also wish to have strings in which you
encrypt the data. And you write an encrypted
DataStream and read back an encrypted Data Stream
decrypt it.
9CDP - Factory Method - Example
encrypted stream
encrypted string
Write to Encrypted Socket
EncryptedSocket
encrypted stream
string
encrypted string
Encrypt Data
Write to Encrypted Socket
EncryptedSocket
encrypted stream
encrypted string
Read from Socket
decrypted string
Decrypt Data
Socket
But now you realize that there are several
different encryption algorithms and codes you
wish to use.
10CDP - Factory Method - Example
The process to encrypt differs in using many
different different algorithms (function/method)
and type of string output must be written for
each type.
encrypted stream
encrypted String 1
Encrypt Data
Write to Encrypted Socket
string
EncryptedSocket
algorithm 1
encrypted stream
encrypted String 2
Encrypt Data
Write to Encrypted Socket
string
EncryptedSocket
algorithm 2
encrypted stream
encrypted String n
Encrypt Data
Write to Encrypted Socket
string
EncryptedSocket
algorithm n
11CDP - Factory Method - Example
The factory pattern allows you to have a
framework that will handle any type of algorithm
and encrypted data.
concrete product
encrypted stream
encrypted String
Encrypt Data
Write to Encrypted Socket
string
EncryptedSocket
algorithm 1
algorithm n
algorithm 2
12CDP - Factory Method - Example
Socket
Socket
4
6
encrypt, decrypt
Product
1
Encryption
EncryptedSocket
EncryptedSocket
1
Creation Requester
DESEncryption
1
5
Transcription
Concrete Product
creates
1
creates
EncryptionFactory
1
3
Factory
requestCreation
EncryptionFactoryIF
Interface
2
13CDP - Factory Method - Example
import java.io.InputStream import
java.io.IOException import java.io.OutputStream
import java.net.Socket import java.security.Key
import java.security.NoSuchAlgorithmException //
This class extends socket to encrypt the stream
of bytes over the net. public class
EncryptedSocket extends Socket private
static Encryption crypt private Key key
14CDP - Factory Method - Example
// Constructor // _at_param Key for
encryption and decryption. // Determines
encryption technique by calling key object's
getAlgorithm() method. // _at_param Factory
object to use to create Encryption objects.
// _at_exception NoSuchAlgorithmException if key
specifies technique not available. public
EncryptedSocket(Key key, EncryptionFactoryIF
factory) throws
NoSuchAlgorithmException this.key
key crypt factory.createEncryption(key)
// Constructor(Key, EncryptionFactoryIF)
15CDP - Factory Method - Example
// Returns an input stream that decrypts the
inbound stream of bytes. // _at_return an
input stream for reading decrypted bytes //
_at_ IOException if an I/O error occurs when
creating the input stream. public
InputStream getInputStream() throws IOException
return crypt.decryptInputStream(super.ge
tInputStream()) // getInputStream()
// Returns an output stream that encrypts the
outbound stream of bytes. // _at_return an
output stream for reading decrypted bytes //
_at_IOException if an I/O error occurs when
creating the output stream. public
OutputStream getOutputStream() throws IOException
return crypt.encryptOutputStream(super.g
etOutputStream()) // getOutputStream()
// class EncryptedSocket
16CDP - Factory Method - Example
import java.io.InputStream import
java.io.OutputStream import java.security.Key //
Abstract class to encrypt/decrypt streams of
bytes. abstract public class Encryption
private Key key // Constructor _at_param
key The key to use to perform the encryption.
public Encryption(Key key) this.key
key // Constructor(Key) //
Return the key this object used for encryption
and decryption. protected Key getKey()
return key // getKey()
17CDP - Factory Method - Example
// This method returns an OutputStream. // It
encrypts bytes written to it. // And it writes
the encrypted bytes to the given OutputStream. //
_at_param out OutputStream that OutputStream
returned writes encrypted bytes. abstract
OutputStream encryptOutputStream(OutputStream
out) // This method returns an
InputStream. // It decrypts the stream of bytes
read from the given InputStream. // _at_param in
InputStream that InputStream returned reads
bytes. abstract InputStream
decryptInputStream(InputStream in) // class
Encrypt
18CDP - Factory Method - Example
import java.security.Key import
java.security.NoSuchAlgorithmException // This
interface must be implemented by all factory
classes // that are used to create instances of
subclasses of Encryption. public interface
EncryptionFactoryIF // Returns an instance
of appropriate subclass of Encryption. //
The instance is determined from information
provided by the given Key object. // _at_param
key will be used to perform the
encryption. public Encryption createEncryption(Ke
y key) throws NoSuchAlgorithmException //
interface EncryptionFactoryIF
19CDP - Factory Method - Example
import java.security.Key import
java.security.NoSuchAlgorithmException // This
class creates instances of appropriate subclasses
of Encryption. //The appropriate subclass is
determined by calling the Key object's public
class EncryptionFactory
20CDP - Factory Method - Example
// Returns an instanace of the appropriate
subclass of Encryption. // It is determined
by the given Key object's getAlgorithm method.
// _at_param key The key that will be used to
perform the encryption. public Encryption
createEncryption(Key key) throws
NoSuchAlgorithmException String
algorithm key.getAlgorithm() if
("DES".equals(algorithm)) return new
DESEncryption(key) if ("RSA".equals(algor
ithm)) return new RSAEncryption(key)
throw new NoSuchAlgorithmException(algorithm)
// createEncryption(Key) // class
EncryptionFactory
21CDP - Factory Method - Example
import java.io.InputStream import
java.io.FilterInputStream import
java.io.FilterOutputStream import
java.io.OutputStream import java.security.Key //
class to DES encrypt/decrypt streams of
bytes. public class DESEncryption extends
Encryption / Constructor
_at_param key The key to use to perform the
encryption. / public DESEncryption(Key
key) super(key) // Constructor(Key)
22CDP - Factory Method - Example
// Returns an OutputStream that encrypts the
bytes written to it/ // And writes the
encrypted bytes to the given OutputStream. //
_at_param out OutputStream that OutputStream
returned by this method writes encrypted
bytes. OutputStream encryptOutputStream(OutputStr
eam out) return new DESEncrytpedOutputSt
ream(out) // encryptOutputStream(OutputStre
am)
23CDP - Factory Method - Example
/ This method returns an InputStream
that decrypts the stream of bytes that it
reads from the given InputStream. _at_param
in The InputStream that the InputStream returned
by this method will read bytes
from. / InputStream decryptInputStream(I
nputStream in) return new
DESEncrytpedInputStream(in) //
decryptInputStream(InputStream)
24CDP - Abstract Factory Method
Synopsis Need for a class for reuse with
abstract classes. Reusable class remains
independent of the classes it instanciates by
delegating the choice of which class to
instanciate to another object and referring to
the newly created object through a common
interface. Context Creates a framework to
support instanciations of various abstract
classes.
25CDP - Abstract Factory Method
Forces Provide services (methods) in a way
transparent to classes using those services.
Solution Proxy object and the service
providing object must either be instances of a
common super class or implement a common
interface. Consequences Could introduce new
failure points.
26CDP - Abstract Factory Method
Suppose you have a textfield or any other GUI
component and you wish to display it on a
particular platform.
Display
windows textfield
27CDP - Abstract Factory Method
Suppose you wish to display those GUI
components on various platforms.
Display
windows textfield
MacOS textfield
Linix textfield
Certainly each platform expects to see different
Java byte code.
28CDP - Abstract Factory Method
Request services
Client
1
uses
uses
Abstract Factory
CPU
Architecture Toolkit
uses
creates
Concrete Factory
EmberCPU
Concrete Product
EmberToolkit
EnginolaCPU
creates
EnginolaToolkit
MMU
creates
1
EmberMMU
EnginolaMMU
requestCreation
29CDP - Abstract Factory Method
// Sample client class shows how a client class
can create concrete widget objects using an
abstract factory public class Client
public void doIt () ArchitectureToolkit
af af ArchitectureToolkit.getFactory(Ar
chitectureToolkit.EMBER) CPU cpu
af.createCPU() //... //doIt //
class Client
30CDP - Abstract Factory Method
// Abstract factory class for creating objects
for remote tests on computer components. public
abstract class ArchitectureToolkit private
static final EmberToolkit emberToolkit new
EmberToolkit() private static
EnginolaToolkit enginolaToolkit new
EnginolaToolkit() //... // Symbolic
names to identify types of computers public
final static int ENGINOLA 900 public final
static int EMBER 901 // ...
31CDP - Abstract Factory Method
// Returns a concrete factory object as an
instance of the concrete factory class. // It
is appropriate for the given computer
architecture. // _at_param architecture - value
indicating architecture that concrete factory
returned for. static final
ArchitectureToolkit getFactory(int architecture)
switch (architecture) case
ENGINOLA return enginolaToolkit
case EMBER return
emberToolkit // ... //
switch String errMsg Integer.toString(ar
chitecture) throw new IllegalArgumentExce
ption(errMsg) // getFactory()
32CDP - Abstract Factory Method
// Method to create objects for remote
testing CPUs. public abstract CPU
createCPU() // Method to create objects
for remote testing MMUs. public
abstract MMU createMMU() //... //
ArchitectureToolkit
33CDP - Abstract Factory Method
// This is a concrete factory class for creating
objects used to perform remote tests. // These
tests are on core components of ember
architecture computers. class EmberToolkit
extends ArchitectureToolkit // Method to
create objects for remote testing ember CPUs.
public CPU createCPU() return new
EmberCPU() // createCPU() // Method
to create objects for remote testing ember MMUs.
public MMU createMMU() return new
EmberMMU() // createMMU() //... //
class EmberToolkit
34CDP - Abstract Factory Method
// This is a concrete factory class for creating
objects used to perform remote tests. // These
tests are on core components of enginola
architecture computers. class EnginolaToolkit
extends ArchitectureToolkit // Method to
create objects for remote testing enginola CPUs.
public CPU createCPU() return new
EnginolaCPU() // createCPU() //
Method to create objects for remote testing
enginola MMUs. public MMU createMMU()
return new EnginolaMMU() // createMMU()
//... // class EnginolaToolkit
35CDP - Abstract Factory Method
// This is an abstract class for objects that
perform remote tests on CPUs. public abstract
class CPU extends ComponentTester //...
// class CPU // This is an abstract class for
objects that perform remote tests on CPUs. public
abstract class CPU extends ComponentTester
//... // class CPU
36CDP - Abstract Factory Method
// Class for objects that perform remote tests
on Ember architecture CPUs. class EmberCPU
extends CPU //... // class EmberCPU //
Class for objects that perform remote tests on
Enginola architecture CPUs. class EnginolaCPU
extends CPU //... // class EnginolaCPU
37CDP - Abstract Factory Method
// This is an abstract class for objects that
perform remote tests on MMUs. public abstract
class MMU extends ComponentTester //...
// class MMU _____________________________________
____________________________________ // Class for
objects that perform remote tests on Enginola
architecture MMUs. class EnginolaMMU extends MMU
//... // class EnginolaMMU _______________
__________________________________________________
________ // Class for objects that perform
remote tests on Ember architecture MMUs. public
class EmberMMU extends MMU //... // class
EmbeMMU
38CDP - Builder
Synopsis Need to build an instance of
an object depending on the type of instance
needed. Context Allows a client object to
construct a complex object by specifying only its
type and content. Forces Program
required to produce multiple external
representations of the same data.
39CDP - Builder
Solution Abstract Builder builds and returns the
data representation needed. Concrete builder,
subclass of abstract builder, used to build a
specific kind of data representation. Consequence
s Provides finer control over construction that
other patterns.
40CDP - Builder
Suppose you have an e-mail gateway program. The
program receives a message in MIME format and
forwards them in a different format for a
different kind of e-mail system.
MIME mail
Forward E-mail
format 1
Destination 1
format 2
Destination 1
format n
Destination 1
You have a procedure (set of methods) for each
format builder routine. The methods are similar
but you need multiple procedures. The builder
pattern allows you to use one method for all
formats.
41CDP - Builder
You want a class to build the format needed
depending on the Destination using a builder
class.
format whatever
MIME mail
Build Format
Forwarded E-Mail
Destination 1
Destination 1
Destination 1
42CDP - Builder
1 receive(MIME)
Director
manages
MessageManager
MIMEMsg
sends
2 parse(MIME)
ProductIF
is parsed by
OutboundMessageIF
4 send
MIMEParser
PRoFMsg
directs
MAPIMsg
Product
3 build
MessageBuilder
creates
1
creates
PROFSBuilder
MAPIBuilder
requestCreation
43CDP - Builder (collaboration diagram)
2 parse(MIME)
1 receive(MIME)
1.1 outMsgparse(msgMIMEMsg)
MIMEParser
MessageManager
1 receive (msgMIMEMsg)
1.2 send( )
1.1.2 to(String) 1.1.3from(String) 1.1.4plain
Text(String) 1.1.5jpegImage(Image) 1.1.6outMsg
getOutboundMsg( )
outMsgOutboundMessageIF
4 send
BuilderMAPIBuilder
1.1.1 buildergetInstance(toString)
MessageBuilder
3 build
44CDP - Builder
import java.awt.Image // This is an abstract
builder class for building e-mail
messages abstract class MessageBuilder //
Return an object of the subclass for the e-mail
message format implied by the destination
address. //_at_param dest The e-mail address
the message is to be sent to static
MessageBuilder getInstance(String dest)
MessageBuilder builder null //...
return builder // getInstance(String)
45CDP - Builder
// pass the value of the "to" header field
to this method. abstract void to(String
value) // pass the value of the "from"
header field to this method. abstract void
from(String value) //... // pass the
value of the "organization" header field to this
method. void organization(String value)
// pass the content of a plain text body part
to this method. abstract void
plainText(String content) // pass the
content of a jpeg image body part to this
method. abstract void jpegImage(Image
content) // complete and return the
outbound e-mail message. abstract
OutboundMessageIF getOutboundMsg() // class
MessageBuilder
46CDP - Builder
// Class used to represent raw MIME e-mail
messages. // If program expanded to receive
messages in formats other than MIME, // then
this will probably become an abstract class with
a subclass for each type of e-mail. public
class MIMEMessage private byte
rawMessage // Constructor _at_param msg A byte
array containing a raw unprocessed e-mail
message. public MIMEMessage(byte
msg) rawMessage msg //
constructor(byte) // Return the raw bytes of
an unprocessed e-mail message. byte
getMessage() return rawMessage //
getMessage() // class MIMEMessage
47CDP - Builder
import java.awt.Image // This is a class to
parse MIME e-mail messages. class MIMEParser
private MIMEMessage msg // The message
being parsed private MessageBuilder builder
// The builder object //...
48CDP - Builder
// parse MIME message, call builder methods for
message's header fields and body parts.
OutboundMessageIF parse(MIMEMessage msg)
this.msg msg builder
MessageBuilder.getInstance(getDestination())
MessagePart hdr nextHeader() while
(hdr ! null) if (hdr.getName().equa
lsIgnoreCase("to"))
builder.to((String)hdr.getValue())
else if (hdr.getName().equalsIgnoreCase("from"))
builder.from((String)hdr.getValue())
//... hdr
nextHeader() // while hdr
49CDP - Builder
MessagePart bdy nextBodyPart() while
(bdy ! null) if (bdy.getName().equa
ls("text/plain")) builder.plainText((String)bdy.
getValue()) //... else if
(bdy.getName().equals("image/jpeg"))
builder.jpegImage((Image)bdy.getValue())
//... bdy nextHeader() // while
body return builder.getOutboundMsg()
// parse(MIMEMessage) private MessagePart
nextHeader() MessagePart mp null
//... return mp // nextHeader()
50CDP - Builder
private MessagePart nextBodyPart()
MessagePart mp null //...
return mp // nextBodyPart() // return
the destination e-mail address for the message
private String getDestination() String
dest null //... return dest
// getDestination()
51CDP - Builder
private class MessagePart private
String name private Object value
// Consructor MessagePart(String name,
Object value) this.name name
this.value value //
Consructor(String, String) String
getName() return name Object
getValue() return value // class
MessagePart // class MIMEParser
52CDP - Builder
// All classes that are used to represent
outbound messages will implement this interface.
public interface OutboundMessageIF public
void send() // interface OutboundMessageIF
53CDP - Prototype
Synopsis Allows creation of customized objects
without knowing their exact class or details of
how to create them. Context Addresses how to
provide a prototype for creating similar
object. Forces Create objects without knowing
their exact class, how created or what data they
represent.
54CDP - Prototype
Solution Create a prototype class that
implements a Prototype interface and are
instantiated for being cloned. Create a prototype
builder to supply prototypical objects. Consequenc
es Additional time is spent writing
prototypebuilder classes.
55CDP - Prototype
Suppose you have a CAD system that allows you to
draw symbols on a screen from a symbol palette
AND you wish to have the user to be able to
create user defined symbols.
symbol selection
Select Symbol
build symbol object
user defined symbol selection
You have a procedure (set of methods) for each
symbol or you have A builder routine for the
symbols. Then for a user defined symbol,
you must set up all possible things you might
wish and allow the user to select methods at
runtime.
56CDP - Prototype
You could allow an object to create a cloned
object from others.
symbol selection
Select Symbol
build symbol selected object
user defined symbol selection
build symbol selected object
Build Prototype Object
user defined symbol selection
The prototype object is built at runtime allowing
the user to use the newly defined symbol based on
some predefined prototype.
57CDP - Prototype
ltltinterfacegtgt Cloneable
Prototype
Client
uses
CharacterManager
Character
create and register objects
Hero
Monster
CharacterLoader
PrototypeBuilder
58CDP - Prototype
import java.awt.Image // Abstract class for
characters. public abstract class Character
implements Cloneable private String name
private Image image private int strength
//... // Override clone to make it public.
Should never have exception public Object
clone() try return
super.clone() catch
(CloneNotSupportedException e) throw new
InternalError() // try // clone()
59CDP - Prototype
public String getName() return name
// getName() public void setName(String
name) this.name name //
setName(String) public Image getImage()
return image // getImage(Image)
public void setImage(Image image)
this.image image // setImage(Image)
public int getStrength() return
strength // getStrength() public void
setStrength(int strength) this.strength
strength // setStrength(int) //... //
class Character
60CDP - Prototype
import java.io.BufferedInputStream import
java.io.FileInputStream import
java.io.InputStream import java.io.ObjectInputStr
eam // This class loads character objects and
adds them to the CharacterManager. class
CharacterLoader private CharacterManager
mgr // Constructor _at_param cm The
CharacterManager that this object will work
with. CharacterLoader(CharacterManager cm)
mgr cm // Constructor
61CDP - Prototype
// Load character objects from specified file.
// Exceptions needed since failure only affects
the program when new character objects are not
loaded. // _at_param fname The name of the file to
read objects from. // _at_return The number of
Charcter objects loaded. int
loadCharacters(String fname) int
objectCount 0 // The number of objects
loaded
62CDP - Prototype
// If construction of the InputStream fails,
just return try InputStream
in in new FileInputStream(fname)
in new BufferedInputStream(in)
ObjectInputStream oIn new
ObjectInputStream(in) while(true)
Object c oIn.readObject()
if (c instanceof Character)
mgr.addCharacter((Character)c) // if
// while catch (Exception e)
// try return objectCount
// loadCharacters(String) // class
CharacterLoader
63CDP - Prototype
import java.util.Vector // Class manages
collection of prototypical objects for the game.
// When asked, it clones appropriate
prototypical object and returns it to requesting
object. public class CharacterManager
private Vector characters new Vector()
//... // Return a random character from the
collection. Character getRandomCharacter()
int i (int)(characters.size()Math.random
()) return (Character)((Character)charact
ers.elementAt(i)).clone() //
getRandomCharacter()
64CDP - Prototype
// Add a prototypical object to the
collection. // _at_param character The character
to add. void addCharacter(Character
character) characters.addElement(charact
er) // addCharacter(Character) //...
// class CharacterManager
65CDP - Prototype
// instances of this class are hero characters.
public class Hero extends Character
private int bravery //... public int
getBravery() return bravery //
getBravery() public void setBravery(int
bravery) this.bravery bravery
// setBravery(int) // class Hero
66CDP - Prototype
// instances of this class are monster
characters. public class Monster extends
Character private int visciousness
//... public int getVisciousness()
return visciousness // getVisciousness()
public void setVisciousness(int visciousness)
this.visciousness visciousness
// setVisciousness(int) // class Monster
67CDP - Singleton
Synopsis Insures only one instance of a class
is created. Context Some classes are used to
manage a resource so they require creation only
once. Forces Requirement for one instance of a
class accessible.
68CDP - Singleton
Solution A static variable that refers to the
one instance of the class you wish to use as a
singleton. Consequences Subclassing is awkward
and results in imperfectly encapsulated classes.
69CDP - Singleton
Suppose you have a audio connection (player)
which plays an Audio but should now allow two
audios to play at one time.
audio play trigger
Play Audio
audio
overlaying audio
If you do not want one audio to overlay the
others (play at the same time), you will have to
write a semaphore to keep multiple audios from
playing.
70CDP - Singleton
Make a singleton which acts as a semaphore to
allow creation of its playing object only once (a
singleton).
audio play trigger
Play Audio
audio
71CDP - Singleton
AudioClipManager
Singleton
72CDP - Singleton
import java.applet.AudioClip // This class
used to avoid playing two audio clips at the same
time. // The class has only one instance accessed
through its getInstance method. // When you play
through that object, it stops the last audio clip
and starts the new one. // If all audio clips are
played through the AudioClipManager object, //
then there will never be more than one audio
clip playing at the same time. public class
AudioClipManager implements AudioClip
private static AudioClipManager myInstance
new AudioClipManager() private AudioClip
prevClip // previously requested audio clip
// Private constructor defined so compiler won't
generate a default public constructor.
private AudioClipManager()
73CDP - Singleton
// Return a reference to the only instance of
this class. public static AudioClipManager
getInstance() return myInstance //
getInstance() // Start playing this audio
clip. Each time method is called, clip is
restarted from beginning. public void play()
if (prevClip ! null) prevClip.play()
// play() // Stop previously requested audio
clip and play the given audio clip. // _at_param
clip the new audio clip to play. public void
play(AudioClip clip) if (prevClip !
null) prevClip.stop() prevClip
clip clip.play() //
play(AudioClip)
74CDP - Singleton
// Starts playing this audio clip in a loop.
public void loop() if (prevClip !
null) prevClip.loop() // loop()
// Stop previously requested audio clip and play
the given audio clip in a loop. // _at_param
clip the new audio clip to play. public
void loop(AudioClip clip) if (prevClip
! null) prevClip.stop() prevClip
clip clip.loop() //
play(AudioClip) // Stops playing this audio
clip. public void stop() if (prevClip
! null) prevClip.stop() // stop() //
class AudioClipManager
75CDP - Singleton
import java.util.HashSet // This class has
methods to ensure that an object is never garbage
collected. public class ObjectPreserver
implements Runnable // This keeps this
class and everything it references from being
garbage collected private static
ObjectPreserver lifeLine new ObjectPreserver()
// Since class won't be garbage collected,
neither will HashSet or object it references.
private static HashSet protectedSet new
HashSet() // Constructor. private
ObjectPreserver() new Thread(this).start()
// constructor() public void run()
try wait() catch (InterruptedException
e) // try // run() // Garbage
collection of objects passed prevented until sent
to unpreserveObject method. public static
void preserveObject(Object o)
protectedSet.add(o) // preserveObject()
// Objects passed to method lose protection
preserveObject method gave from garbage
public static void unpreserveObject(Object o)
protectedSet.remove(o) // unpreserveO.. //
class ObjectPreserver
76CDP - Object Pool
Synopsis Manages reuse of objects when a type
of object is expensive to create or only a
limited number of objects can be created.
Context You wish to limit access to a
resource Forces A program may not create more
than a limited number of instances for a
particular class
77CDP - Object Pool
Solution Create a reusable class to collaborate
with other objects for a limited amount of
time. Create a reusable pool to manage reusable
objects for use by client objects.
Consequences Requests may have to wait for an
object to become unused.
78CDP - Object Pool
Suppose you have a database systems that need to
allow only a limited number of accesses to the
database at one time.
Allow Database Access
database access requested
database access
You must write a counting semaphore to protect
this resource from having more than the limited
access.
79CDP - Object Pool
manage objects
Client
ReusablePool
Reusable Pool
uses
Reusable
80CDP - Object Pool
// Public class used outside database access
library to represent a database
connection. public class Connection private
final static ConnectionImpl.ConnectionPool
connectionPool ConnectionImpl.ConnectionPool.get
Instance() private String databaseName
//... // Send a request to the database and
return the result. Object sendRequest(Request
request) Object result
ConnectionImpl impl connectionPool.acquireImpl(d
atabaseName) result impl.sendRequest(re
quest) connectionPool.releaseImpl(impl)
return result //
sendRequest(Request) // class Connection
81CDP - Object Pool
import java.util.Hashtable import
java.util.Vector // Instances of this class
provide actual connections to a database. class
ConnectionImpl // Name of the datbase this
object connected to. private String dbName
// Private Constructor private
ConnectionImpl(String dbName)
this.dbName dbName //... //
constructor() //... // return the name of the
database that this objects is connected to.
String getDatabaseName() return dbName
// getDatabaseName()
82CDP - Object Pool
// Send a request to the database and return the
result. Object sendRequest(Request request)
Object result null //...
return result // sendRequest(Request)
//... static class ConnectionPool
// The one instance of this class private
static ConnectionPool thePool new
ConnectionPool() // Hash table
associates database names with corresponding
Vector that contains // a pool of
connections for that database. private
Hashtable poolDictionary new Hashtable() //
This constructor is private to prevent other
classes from creating instances of this class.
private ConnectionPool()
83CDP - Object Pool
// Return the one instance of this class.
public static ConnectionPool getInstance()
return thePool // getInstance()
/ Return a ConnectionImpl from
appropriate pool or create one if the pool is
empty. _at_param dbName Name of database
that ConnectionImpl is to be supplied for.
/ public synchronized ConnectionImpl
acquireImpl(String dbName) Vector
pool (Vector)poolDictionary.get(dbName)
if (pool ! null) int size
pool.size() if (size gt 0)
return (ConnectionImpl)pool.remove(size-1)
// if null // No
ConnectionImpl in pool, so create one.
return new ConnectionImpl(dbName) //
acquireImpl(String)
84CDP - Object Pool
/ Add a ConnectionImpl to
the appropriate pool. / public
synchronized void releaseImpl(ConnectionImpl
impl) String databaseName
impl.getDatabaseName() Vector pool
(Vector)poolDictionary.get(databaseName)
if (pool null) pool
new Vector() poolDictionary.put(d
atabaseName, pool) // if null
pool.addElement(impl) //
releaseImpl(ConnectionImpl) // class
ConnectionPool // class ConnectionImpl
85CDP - Object Pool
/ Objects used to transmit requests to the
database implment this interface.
/ interface Request //... // interface
Request