Title: Structural Patterns
1Structural Patterns
Adapter Dynamic Linkage Iterator Virtual
Proxy Bridge Decorator Façade Cashe
Management Flyweight
2SP - Adapter
Synopsis Implements an interface known to its
clients and provides access to an instance of a
class not known to its clients.
Context Defining an interface that declares a
method that the array copier calls to find out if
it should include a particular object in the new
array.
3SP - Adapter
Forces You want to use a class that calls a
method through an interface, but you want to use
it with a class that does not implement that
interface. Solution Arrange for the instance
to make the call through an adapter object that
implements the interface with a method that calls
a method that doesnt implement the
interface. Consequences Introduces additional
indirection into a program.
4SP - Adapter
Suppose you want to have a process which filters
an array and produces another array
filtered array
Filter Array
array
But you also wish to have the method independent
of the filtering criteria because you wish to
reuse the method for both arrays you wish to
filter and those you do not wish to filter.
filtered array
Filter Array
array
unf iltered array
5SP - Adapter
Client
uses
Client
TargetIF
uses
Adaptee
Adapter
6SP - Adapter
// Instances of this class represent a
customer class Customer //... Class
Attributes of Customer private String
shipToAddress1 // the first line of ship-to
street address. private String shipToAddress2
// the second line of ship-to street address.
private String shipToCity // ship-to city.
private String shipToState // ship-to state.
private String shipToPostalCode // ship-to
postal code private String billToAddress1 //
the first line of bill-to street address.
private String billToAddress2 // the second line
of bill-to street address. private String
billToCity // bill-to city. private String
billToState // bill-to state. private String
billToPostalCode // bill-to postal code
7SP - Adapter
// gets and sets for attributes of customer
public String getShipToAddress1() return
shipToAddress1 // Get first line of ship-to
public void setShipToAddress1(String address1)
// Set first line of ship-to street addr
shipToAddress1 address1 //
setShipToAddress1 public String
getShipToAddress2() return shipToAddress2
// Get second line public void
setShipToAddress2(String address2) // Set
second line of ship-to addr
shipToAddress2 address2 //
setShipToAddress2(String) public String
getShipToCity() return shipToCity // Get
ship-to city public void setShipToShipToCity(St
ring city) billToCity city // Set ship-to
city public String getShipToState() return
shipToState // Get ship-to state public
void setShipToState(String state) shipToState
state // Set ship-to state public String
getShipToPostalCode() return shipToPostalCode
// get ship-to postal public void
setShipToPostalCode(String postalCode) // set
ship-to postal code shipToPostalCode
postalCode // setShipToPostalCode(String)
public String getBillToAddress1() return
billToAddress1 // Get first line of bill-to
// ..many more
8SP - Adapter
// Adapter class allows objects that access
AddressIF to access customer's address. class
CustomerBillToAdapter implements AddressIF
private Customer myCustomer public
CustomerBillToAdapter(Customer customer)
myCustomer customer // constructor
public String getAddress1() return
myCustomer.getBillToAddress1() // Get first
line public void setAddress1(String
address1) // Set first line of street address
myCustomer.setBillToAddress1(address1)
// setAddress1(String)
9SP - Adapter
public String getAddress2() return
myCustomer.getBillToAddress2() // Get second
line public void setAddress2(String address2)
// Set second line of street address
myCustomer.setBillToAddress2(address2) //
setAddress2(String) public String getCity()
return myCustomer.getBillToCity() // Get the
city public void setCity(String city) //
Set the city myCustomer.setBillToCity(city
) // setCity(String) public String
getState() return myCustomer.getBillToState()
// Get the state // and many more
10SP - Adapter
import guiframework.AboutDialog import
guiframework.MainFrame import java.awt. import
java.awt.event.ActionEvent import
java.awt.event.ActionListener class MenuFrame
extends MainFrame // Class is top level frame
for JCase private AboutDialog aboutDialog
private Panel drawingPanel // The current
controler element determines the mouse pointer
being // used and the action taken for a
mouse click. private DrawingController
currentDrawingController
11SP - Adapter
MenuFrame() // constructor DRAWING
PANEL super(ResourceManager.getString(Reso
urceManager.TITLE_MAIN)) createMenus()
addNotify() Dimension screenSize
getToolkit().getScreenSize()
setSize(screenSize) drawingPanel new
Panel() drawingPanel.setBackground(Color.
white) drawingPanel.setForeground(Color.b
lack) add(drawingPanel,
BorderLayout.CENTER) // Temporary code
drawingPanel.addMouseListener(new
TextController(drawingPanel)) //
constructor()
12SP - Adapter
// build this frame's menus private void
createMenus() String caption
caption ResourceManager.getString(ResourceManage
r.FILE) Menu fileMenu new
Menu(caption) fileMenu.add(new
MenuItem("-")) caption
ResourceManager.getString(ResourceManager.EXIT)
MenuItem exit new MenuItem(caption)
exit.addActionListener(new ActionListener()
public void actionPerformed(ActionEv
ent evt) close() // actionPerformed
) fileMenu.add(exit)
13SP - Adapter
caption ResourceManager.getString(Resou
rceManager.ADD) Menu addMenu new
Menu(caption) caption
ResourceManager.getString(ResourceManager.TEXT_BOX
) MenuItem textBox new
MenuItem(caption) addMenu.add(textBox)
caption ResourceManager.getString(Resour
ceManager.HELP) Menu help new
Menu(caption) caption
ResourceManager.getString(ResourceManager.ABOUT)
MenuItem about new MenuItem(caption)
about.addActionListener(new
ActionListener() public void
actionPerformed(ActionEvent evt) showAbout()
// actionPerformed )
help.add(about)
14SP - Adapter
MenuBar mb new MenuBar()
mb.add(fileMenu) mb.add(addMenu)
mb.setHelpMenu(help) setMenuBar(mb)
// createMenus() void showAbout() //
Show this frames about dialog String
title title ResourceManager.getString(R
esourceManager.TITLE_ABOUT) String
message message ResourceManager.getStri
ng(ResourceManager.ABOUT_MESSAGE) if
(aboutDialog null) aboutDialog new
AboutDialog(this, title, message) // if
aboutDialog.show() // showAbout() //
class MenuFrame
15SP - Adapter
import java.awt. import java.awt.event.ActionEve
nt import java.awt.event.ActionListener public
class OK extends Frame public static void
main(String argv) OK app new OK()
app.setVisible(true) //
main(String)
16SP - Iterator
Synopsis An interface that declares methods for
sequentially accessing the objects of a
collection. Context Allows browsing of a
collection of objects. Forces A class needs
access to the contents of a collection without
becoming dependent on the class used to implement
tht collection.
17SP - Iterator
Solution Collection encapsulates the collection
of objects, interface defines methods to
sequentially access the objects, and the iterator
implements the iterator interface with instances
providing sequential access to contents of the
collection. Consequences Possible to access
collection without knowing source of the object.
18SP - Iterator
You with to browse through a collection.
Query Collection
response
request
But you do not wish to have to know what the
objects are within the collection because you
wish to reuse the iterator.
19SP - Iterator Inventory Pattern
gets
InventoryBrowser
displays
IteratorIF
InventoryIteratorIF
InventoryItem
gets
InventoryIterator
InventoryCollection
Iterator
Collection
20SP - Iterator
public class InventoryCollection //...
public InventoryIteratorIF iterator() //
Return an Iterator for this object return
new InventoryIterator() // iterator()
private class InventoryIterator implements
InventoryIteratorIF public boolean
hasNextInventoryItem() //...
// hasNextInventoryItem() public
InventoryItem getNextInventoryItem()
//... // getNextInventoryItem()
21SP - Iterator
public boolean hasPrevInventoryItem()
//... // hasPrevInventoryItem
() public InventoryItem
getPrevInventoryItem() //...
// getPrevInventoryItem() // class
InventoryIterator // ... // class
InventoryCollection/ // Instances of this
class describe an inventory item
22SP - Iterator
public class InventoryItem //... //
class InventoryItem public interface
InventoryIteratorIF public boolean
hasNextInventoryItem() public InventoryItem
getNextInventoryItem() public boolean
hasPrevInventoryItem() public InventoryItem
getPrevInventoryItem() // interface
InventoryIterator
23SP - Bridge
Synopsis Hierarchy of abstractions and a
corresponding hierarchy of implementations.
Context You wish to provide a generalized
access to control devices in control
applications. Forces You want to reuse logic
common to different implementations of an
abstraction.
24SP - Bridge
Solution Maintain a clean separation between the
devices and the controlling by having an
abstraction class access the implementation
classes through interfaces in a hierarchy that
parallels the inheritance hierarchy of the
abstraction. Consequences Classes that are
clients of an abstraction dont posses any
knowledge of the implementation classes.
25SP - Bridge
Suppose you wish to have some physical devices
connected to the computer and have a common
interface for the devices.
Measure Pounds
pounds
Device1
scale measurement
Measure Speed
mph
Device2
speed measurement
Measure n
Device3
n measurement
But you wish to have a reusable common interface
for measuring.
Measure Values
value
Devicen
measurement
26SP - Bridge Sensor Example
StreamingSensor
SimpleSensor
AveragingSensor
Abstraction
I could have this abstraction hierarchy.
27SP - Bridge Sensor Example
EagleStreamingSensor
EagleSimpleSensor
EagleAveragingSensor
HawkAveragingSensor
HawkSimpleSensor
HawkStreamingSensor
With this implementation hierarchy.
28SP - Bridge Sensor Example
I do not want to write a class for each sensor
distributed from the vendors. I do not want
to write a class for streaming vs simple sensors
for each distributed vendor. I want to bridge
these types.
29SP - Bridge Sensor Example
StreamingSensor
SimpleSensor
SpecializedAbstraction
AveragingSensor
uses
uses
Abstraction
uses
StreamingSensorImpl
SimpleSensorImpl
AverageSensorImpl
AbstractionImpl
SpecializedAbstractionImpl
EagleStreamingSensor
EagleSimpleSensor
EagleAveragingSensor
HawkAveragingSensor
HawkSimpleSensor
HawkStreamingSensor
30SP - Bridge
// Instances used to represent sensors that
produce values the average of measurements public
class AveragingSensor extends SimpleSensor
// Constructor intended to be called by a factory
method object // same package as this
class and classes that implement its operations.
// _at_param impl Implements the sensor
type-specific operations this object provides.
AveragingSensor(AveragingSensorImpl impl)
super(impl) // constructor //... //
Averaging sensors produce an average of
measurements made over a period of time. //
_at_exception SensorException if there is a problem
accessing the sensor. public void
beginAverage() throws SensorException
((AveragingSensorImpl)getImpl()).beginAverage()
// beginAverage() // class AveragingSensor
31SP - Bridge
// All objects that implement operations for
AveragingSensor objects must // implement this
interface. interface AveragingSensorImpl extends
SimpleSensorImpl // Averaging sensors
produce a value that is average of measurements
over a time period // That period of time
begins when this method is called. //
_at_exception SensorException if there is a problem
accessing the sensor. public void beginAverage()
throws SensorException // interface
AveragingSensorImpl
32SP - Bridge
// This class impelments AveragingSensor
operations for sensors made by Eagle. class
EagleAveragingSensor extends EagleSimpleSensor
implements AveragingSensorImpl // Averaging
sensors produce a value - average of measurements
made over a time period. // That period of
time begins when this method is called. //
_at_exception SensorException if there is a problem
accessing the sensor. public void
beginAverage() throws SensorException
//... // beginAverage() // class
EagleAveragingSensor
33SP - Bridge
// This class implements SimpleSensor operations
for sensors made by Eagle. class
EagleSimpleSensor implements SimpleSensorImpl
// Return the value of the sensor's current
measurement. // _at_exception SensorException if
there is a problem accessing the sensor.
public int getValue() throws SensorException
int value //... return
value // getValue() // class
EagleSimpleSensor
34SP - Bridge
// Class implements StreamingSensor operations
for sensors made by Eagle. class
EagleStreamingSensor extends EagleSimpleSensor
implements StreamingSensorImpl // Streaming
sensors produce a stream of measurement values
produced with a // frequency no greater than
the given number of times per minute. //
_at_param freq Max times per minute this streaming
sensor produces a measurement // This class
impelments StreamingSensor operations for sensors
made by Eagle. public void setSamplingFrequenc
y(int freq) throws SensorException
//... // setSamplingFrequency(int)
35SP - Bridge
// Method called by an object representing
streaming sensor abstraction // so that this
object can perform a call-back to that object to
deliver measurement values to it. // _at_param
abstraction The abstraction object to deliver
measurement values to. public void
setStreamingSensorListener(StreamingSensorListener
listener) //... //
setStreamingSensorListener(StreamingSensorListener
) // class EagleStreamingSensor
36SP - Bridge
// This class impelments AveragingSensor
operations for sensors made by Hawk. class
HawkAveragingSensor extends HawkSimpleSensor
implements AveragingSensorImpl // Averaging
sensors produce a value - the average of
measurements made over a time period. //
That period of time begins when this method is
called. // _at_exception SensorException if
there is a problem accessing the sensor.
public void beginAverage() throws SensorException
//... // beginAverage() //
class HawkAveragingSensor
37SP - Bridge
// This class impelments StreamingSensor
operations for sensors made by Hawk. class
HawkStreamingSensor extends HawkSimpleSensor
implements StreamingSensorImpl // Streaming
sensors produce a stream of measurement values.
// The stream of values produced with
frequency no greater than number of times per
minute. // _at_param freq The maxnumber of times
per minute streaming sensor produces a value
// _at_exception SensorException if there is a
problem accessing the sensor. public void
setSamplingFrequency(int freq) throws
SensorException //... //
setSamplingFrequency(int) // Method is called
by an object representing the streaming sensor
abstraction // so that this object can perform
a call-back to that object to deliver measurement
values to it. // _at_param abstraction The
abstraction object to deliver measurement
values to. public void setStreamingSensorListene
r(StreamingSensorListener listener)
//... // setStreamingSensorListener(Streamin
gSensorListener) // class HawkStreamingSensor
38SP - Bridge
// Instances are thrown by methods that access
sensors when they encounter an error public
class SensorException extends Exception //
Constructor _at_param msg message string to
associate with this exception object.
public SensorException(String msg)
super(msg) // Constructor(String) //
class SensorException // Instances of this class
are used to represent all kinds of sensors. //
Instances of subclasses of this class represent
specialized kinds of sensors. public class
SimpleSensor // A reference to the object
that implements operations specific to // the
actual sensor device that this object
represents. private SimpleSensorImpl impl //
Constructor intended to be called by a factory
method object that is in the same // package as
this case and the classes that implement its
operations. // _at_param impl Object that implements
ensor type-specific operations this object
provides
39SP - Bridge
SimpleSensor(SimpleSensorImpl impl)
this.impl impl // constructor(SimpleSensorIm
pl) // allows subclasses of this class to get
the reference to implementation object
protected SimpleSensorImpl getImpl() return
impl // getImpl() //... // Return
the value of the sensor's current measurement.
// _at_exception SensorException if there is a
problem accessing the sensor. public int
getValue() throws SensorException return
impl.getValue() // getValue() // class
SimpleSensor
40SP - Bridge
// All objects that implement operations for
SimpleSensor objects must // implement this
interface. interface SimpleSensorImpl //
Return the value of the sensor's current
measurement. // _at_exception SensorException if
there is a problem accessing the sensor. public
int getValue() throws SensorException //
interface SimpleSensorImpl
41SP - Bridge
import java.io.DataInputStream import
java.io.DataOutputStream import
java.io.IOException import java.io.PipedInputStre
am import java.io.PipedOutputStream import
java.util.Vector // Instances of class used to
represent sensors that produce a stream of
measurement values. public class StreamingSensor
extends SimpleSensor implements
StreamingSensorListener, Runnable //
Objects are used to provide a buffer allowing
implementation object to asynchronously //
deliver measurement values while this object
deslivers value it already received tolisteners.
private DataInputStream consumer private
DataOutputStream producer private Vector
listeners new Vector() // aggregate listeners
here
42SP - Bridge
// Constructor intended to be called by a
factory method object that is in same package as
// this class and the classes that implement
its operations. // _at_param impl Object
implements sensor type-specific operations this
object will provide. // _at_exception
SensorException if initialization of this object
fails. StreamingSensor(StreamingSensorImpl
impl) throws SensorException
super(impl) // at the same time it is
receiving them. PipedInputStream
pipedInput new PipedInputStream()
consumer new DataInputStream(pipedInput)
PipedOutputStream pipedOutput
43SP - Bridge
try pipedOutput new
PipedOutputStream(pipedInput) catch
(IOException e) throw new SensorException("pipe
creation failed") // try
producer new DataOutputStream(pipedOutput)
// start a thread to deliver measurement values
new Thread(this).start() //
constructor(StreamingSensorImpl) //...
44SP - Bridge
// Streaming sensors produce a stream of
measurement values. // The stream of values
produced with frequency no greater than given
numberper minute. // _at_param freq The max times
per minute that streaming sensor produces a
value. // _at_exception SensorException if there
is a problem accessing the sensor. //
public void setSamplingFrequency(int freq) throws
SensorException // delegate this to the
implementation object ((StreamingSensorImp
l)getImpl()).setSamplingFrequency(freq) //
setSamplingFrequency(int)
45SP - Bridge
// StreamingSensor objects deliver a stream
of values to interested objects // by
passing each value to the objects
processMeasurement method. // The delivery
of values is done using its own thread and is
asynchronous of everyting else. // _at_param
value The measurement value being delivered.
public void processMeasurement(int value)
try producer.writeInt(value)
catch (IOException e) // If the
value cannot be delivered, just discard it.
// try // processMeasurement(int)
46SP - Bridge
// Method registers its argument as a
recipient of future measurement values from this
sensor. public void addStreamingSensorListener
(StreamingSensorListener listener)
listeners.addElement(listener) //
addStreamingSensorListener(StreamingSensorListener
) // Method unregisters its argument as
recipient of future measurement values from
sensor. public void removeStreamingSensorL
istener(StreamingSensorListener listener)
listeners.removeElement(listener) //
addStreamingSensorListener(StreamingSensorListener
)
47SP - Bridge
// Asynchronously removes measurements from the
pipe and delivers to registered listeners.
public void run() while (true)
int value try value
consumer.readInt() catch (IOException e)
return // try for (int i0
i lt listeners.size() i)
StreamingSensorListener listener
listener (StreamingSensorListener)listen
ers.elementAt(i)
listener.processMeasurement(value)
// for // while // run() //
class StreamingSensor
48SP - Bridge
// Objects implement in operations for
StreamingSensor objects must implement this
interface. interface StreamingSensorImpl extends
SimpleSensorImpl // Streaming sensors
produce a stream of measurement values. //
The stream of values produced with a frequency no
greater than given times per minute. // _at_param
freq The max times per minute that streaming
sensor produces a value. // _at_exception
SensorException if there is a problem accessing
the sensor. public void setSamplingFrequency(
int freq) throws SensorException // Method
called by an object representing streaming sensor
abstraction // so this object can perform a
call-back to that object to deliver measurement
values to it. // _at_param abstraction The
abstraction object to deliver measurement values
to. public void setStreamingSensorListener(Str
eamingSensorListener listener) // interface
StreamingSensorImpl
49SP - Bridge
// This interface is implemented by all objects
able to receive a stream of measurement
values. public interface StreamingSensorListener
// StreamingSensor objects deliver a stream
of values to interested objects // by
passing each value to the object's
processMeasurement method. // The delivery
of values is done using its own thread and is
asynchronous of everyting else. // _at_param
value The measurement value being delivered.
public void processMeasurement(int value) //
interface StreamingSensorListener
50SP - Facade
Synopsis Simplifies access to a related set of
objects by providing one object that all objects
outside the set use to communicate with the set.
Context Having a solution that requires the
developer to know details regarding many classes
adds to the complexity of the solution. This
pattern allows a logical abstraction.
51SP - Facade
Forces Many dependencies exist between classes
that implement an abstraction. These dependencies
add complexity to the problem space.
Solution Have the client object act as a façade
pattern. Consequences Clients of façade objects
dont need to know about any of the classes
behind the façade.
52SP - Facade
You wish to perform a function that involves many
classes with dependencies that add complexity.
Create E-mail
Send E-mail
message
sent e-mail
information
This has nothing to do with processes but instead
has to do with the structure of collaborating
objects and percisely the clustering of those
objects inside a class (a façade).
53SP - Façade - Mail Example
Client
creates
creates
creates
MessageSender
creates
creates
Security
Attachment
contains
MessageHeader
contains
Message
contains
sends
MessageBody
54SP - Façade Reusable example
Clients
uses
MessageCreater
creates
creates
creates
MessageSender
creates
creates
Security
Attachment
contains
MessageHeader
contains
Message
contains
sends
MessageBody
55SP - Façade
Clients
uses
Facade
56SP - Facade
/ Instances of this class encapsulate message
attachments class Attachment // Constructor
_at_param content An object that supplies the
content for this attachment.
Attachment(Object content) //...
// Constructor(Object) //... // class
Attachment // Instances of this class encapsulate
e-mail messages. class Message //
Constructor _at_param header message header.
_at_param body The message body.
Message(MessageHeader header, MessageBody body)
//... // constructor(MessageHeader,
MessageBody) Set Security object used to sign
itself. void setSecurity(Security s)
//... // setSecurity(Security) //...
// class Message
57SP - Facade
// Instances of this class encapsulate the
messge body for an e-mail message. class
MessageBody // Constructor
_at_param body the content of the message
body MessageBody(RichText body) //...
// Constructor(RichText) // Add
attachment to this message body. _at_param
attachment object to add tomessage. void
addAttachment(Attachment attachment)
//... // addAttachment(Attachment) //
class MessageBody
58SP - Facade
import java.util.Hashtable import
java.util.Vector // Instances are used to create
and send e-mail messages. // Assumes an e-mail
message consists of a message body and 0..n
attachments. // Body provided as either a String
or an object implementing interface RichText. //
Any kind of an object can be provided as the
content of an attachment. public class
MessageCreator // Constants to indicate the
type of message to create public final static
int MIME 1 public final static int MAPI
2 public final static int NOTES 3
public final static int BANYAN 4 private
Hashtable headerFields new Hashtable()
private RichText messageBody private Vector
attachments new Vector() private boolean
signMessage
59SP - Facade
// Constructor to create a MessageCreator
object that creates an e-mail message // and
sends it to an address. It tries to infer type
of message to create from to address //
_at_param to The address that this object will send
a message to. // _at_param from The address
that the message will say it is from. //
_at_param subject The subject of this message.
public MessageCreator(String to, String from,
String subject) this(to, from ,
subject, inferMessageType(to)) //
Constructor(String, String, String)
60SP - Facade
// Constructor to create a MessageCreator object
that creates an e-mail message // and sends to
the given address. It will attempt to infer type
of message from "to" address. // _at_param to
The address that this object will send a message
to. // _at_param from The address that the
message will say it is from. // _at_param
subject The subject of this message. //
_at_param type The type of message to create.
public MessageCreator(String to, String from,
String subject, int type)
headerFields.put("to", to)
headerFields.put("from", from)
headerFields.put("subject", subject)
//... // Constructor(String, String,
String, int)
61SP - Facade
// Set contents of message body. _at_param
messageBody contents of the message body.
public void setMessageBody(String messageBody)
setMessageBody(new RichTextString(messageBo
dy)) // setMessageBody(String) // Set
contents of contents body. _at_param messageBody
contents of the message body. public void
setMessageBody(RichText messageBody)
this.messageBody messageBody //
setMessageBody(RichText) // Add an attachement
to message _at_param attachment object to attach
to message public void addAttachment(Object
attachment) attachments.addElement(attac
hment) // addAttachment(Object) // set
whether this message should be signed. The
default is false. public void
setSignMessage(boolean signFlag)
signMessage signFlag //
setSignMessage(boolean)
62SP - Facade
// Set the value of a header field. _at_param
name The name of the field to set the value of //
_at_param value The value to set the field
to. public void setHeaderField(String name,
String value) headerFields.put(name.toLo
werCase(), value) // setHeaderField(String,
String) // Send the message. public void
send() MessageBody body new
MessageBody(messageBody) for (int i 0
i lt attachments.size() i)
body.addAttachment(new Attachment(attachments.elem
entAt(i))) // for
MessageHeader header new MessageHeader(headerFie
lds) Message msg new Message(header,
body) if (signMessage)
msg.setSecurity(createSecurity()) // if
createMessageSender(msg) // send()
63SP - Facade
// Infer an message type from a destination
e-mail address. _at_param e-mail address. private
static int inferMessageType(String address)
int type 0 //... return
type // inferMessageType(String) //
Create a Security object appropriate for signing
this message. private Security
createSecurity() Security s null
//... return s //
createSecurity() // Create a MessageSender
object appropriate for the type of message being
sent. private void createMessageSender(Message
msg) //... // createMessageSender
(Message) //... // class MessageCreator
64SP - Facade
import java.util.Hashtable / Instances of
this class encapsulate header information.
/ class MessageHeader /
constructor _at_param fields A Hashtable that
contains the field values for this
header. / MessageHeader(Hashtable
fields) //... //
constructor(Hashtable) //... // class
MessageHeader
65SP - Facade
// Instances of this class are responsible for
sending e-mail messages on their way. class
MessageSender //... // class
MessageSender // contents of message must either
come from a String object orobject the implements
this interface. public interface RichText
//... // interface RichText // Instances of
this class encapsulate a string for inclusion in
message bodies. class RichTextString implements
RichText private String text /
Constructor _at_param text The string that this
object adapts to the RichText
interface. public RichTextString(String text)
this.text text //... //
constructor(String) //... // class
RichTextString // Instances encapsulate an
algorithm and information for signing an e-mail
message. class Security //... // class
Security
66SP - Flyweight
Synopsis Instances that contain the same
information can be used interchangably to allow a
program to avoid the expense of multiple
instances that contain the same information by
sharing only one of the instances.
67SP - Flyweight
Suppose you wish to write a word processor such
as WORD.
Process Elements
stream
Word Doc
document element
The document element may be a document character,
document, page, paragraph, line of text, or a
container containing any of the previously
mentioned elements. The document character may
be a a..Z special characters. We do not
want an object for every a in the document.
68SP - Flyweight
edits
Document
Application
1
MyDocument
May be doc, xls, or ppt.
69SP - Flyweight
// Instances of this class contain extrinsic
attributes of ranges of characters. class
CharacterContext extends DocumentContainer
//... // class CharacterContext // Instances of
this class represent a character in a
document. class DocChar extends DocumentElement
private char character // Constructor
_at_param c the character that this object
represents. / DocChar (char c)
character c // Constructor(char)
//... public char getChar() return
character // Returns character this object
represents // Method returns unique value
that determines where stored internally in a
hash table. public int hashCode()
return getChar() // hashCode()
70SP - Flyweight
// Redefine equals so two DocChar objects are
considered equal if same character. public
boolean equals(Object o) // Call
getChar rather than access character directly so
method has alternate way a subclass has of
// providing the character it represents.
return (o instanceof DocChar
((DocChar)o).getChar() getChar()) //
equals(Object) // class DocChar
71SP - Flyweight
// Return DocChar object representing given
character. _at_param c character represented.
DocChar getDocChar(char c)
myChar.setChar(c) DocChar thisChar
(DocChar)docCharPool.get(myChar) if
(thisChar null) thisChar new
DocChar(c) docCharPool.put(thisChar,
thisChar) // if return
thisChar // getDocChar(char) //
Instances of this class represent a
document. class Document extends
DocumentContainer //... // class Document
72SP - Flyweight
// We need a DocChar object representing same
character as the DocChar object // Creating a
DocChar object for each lookup defeats purpose
DocChar objects in collection. // Purpose - avoid
creating a DocChar object for each character -use
one DocChar instead // Problem -changing
character DocChar represents since DocChar
objects are immutable. // To get around the
problem NO WAY TO CHANGE CHAR of DocChar
object // use private subclass of DocChar
providing a way to change the character it
represents. private class MutableDocChar extends
DocChar private char character
MutableDocChar() // Constructor
super('\u0000') // It doesn't matter what we
pass to super. // Constructor(char)
// Return the character that this object
represents. public char getChar()
return character // getChar()
// Set character this object represents.
_at_param c public void setChar(char c)
character c // setChar(char) //
class MutableDocChar // class DocCharFactory
73SP - Flyweight
import java.awt.Font import java.util.Vector //
Instances are composite objects that contain
DocumentElement objects. abstract class
DocumentContainer extends DocumentElement
// Collection of this object's children
private Vector children new Vector() //
Font associated with object. If font null, this
objects font inherited through container
private Font font DocumentContainer parent
// this object's container // Return child
object at the given position. _at_param index The
index of the child. public DocumentElement
getChild(int index) return
(DocumentElement)children.elementAt(index)
// getChild(int)
74SP - Flyweight
// Make the given DocumentElement a child of
this object. public synchronized void
addChild(DocumentElement child)
synchronized (child)
children.addElement(child) if (child
instanceof DocumentContainer) ((DocumentContainer)
child).parent this // synchronized
// addChild(DocumentElement) // Make the
given DocumentElement NOT a child of this
object. public synchronized void
removeChild(DocumentElement child)
synchronized (child) if (child
instanceof DocumentContainer
this ((DocumentContainer)child).parent)
((DocumentContainer)child).parent null
children.removeElement(child)
// synchronized // removeChild(DocumentEle
ment)
75SP - Flyweight
// Return this object's parent or null if it
has no parent. public DocumentContainer
getParent() return parent //
getParent() // Return Font associatiated
with this object. No Font , take parent font
public Font getFont() if (font ! null)
return font else if (parent !
null) return parent.getFont()
else return null // getFont()
// Associate a Font with this object. _at_param font
The font to associate with this object public
void setFont(Font font) this.font
font // setFont(Font) //... // class
DocumentContainer
76SP - Flyweight
// All elements of a document belong to a
subclass of this abstract class. abstract class
DocumentElement //... // class
DocumentElement // Instances of this class
represent a line of text. class LineOfText
extends DocumentContainer //... // class
LineOfText // Instances of this class represent
a paragraph. class Paragraph extends
DocumentContainer //... // class Paragraph
77SP - Dynamic Linkage
Synopsis Allow a program , upon request, to
load and use arbitrary classes that implement a
known interface. Context Suppose you have
a food processor and you wish the food processor
to process various types of food using different
techniques or methods.
78SP - Dynamic Linkage
Forces A program wishes to load an
arbitrary class of which it has no knowledge of
and this instance must be able to call back to
the calling program. Solution Create a
dynamic linkage pattern to load the appropriate
class and link back to the calling
class. Consequences Increases time to load.
79SP - Dynamic Linkage
We wish to have a food processor To process
particular food in a certain way.
Process Food
processedfood
Product
foodtype
80SP - Dynamic Linkage
Abstract LoadableClass
EnviornmentIF
uses
FoodProcessor EnvironmentIF
AbstractFood ProcessorProgram
1
uses
Concrete LoadableClass
ConcreteFood ProcessorProgram
FoodProcessor Environment
Enviornment
81SP - Dynamic Linkage
// Top level classes of food processor are
subclasses of this class public abstract class
AbstractFoodProcessorProgram private
FoodProcessorEnvironmentIF environment //
Food processor environment passes a reference to
itself to this method. // That instances of
subclasses call methods of the food processor
environment object // that implements the
FoodProcessorEnvironmentIF interface. public
void setEnvironment(FoodProcessorEnvironmentIF
environment) this.environment
environment // setEnvironment(FoodProcessor
EnvironmentIF)
82SP - Dynamic Linkage
// Allow subclasses to fetch the reference to
the environement. protected
FoodProcessorEnvironmentIF getEnvironment()
return environment //
getEnvironment() // Return the name of this
food processing program object. public
abstract String getName() // A method call
tells a food processing program to start
performing its functions. / public abstract
void start() //... // class
AbstractFoodProcessorProgram
83SP - Dynamic Linkage
// Top level classes of food processor are
subclasses of this class public class
ConcreteFoodProcessorProgram extends
AbstractFoodProcessorProgram // Return
the name of this food processing program object.
public String getName() return "Chocolate
Milk" // A call to this method tells a
food processing program to start. public void
start() double weight
getEnvironment().weigh() if (weight gt
120.0 weight lt 160.0) getEnvironment().mix
(4) //... // start() //...
// class ConcreteFoodProcessorProgram
84SP - Dynamic Linkage
import java.net.URL import java.net.URLClassLoade
r // Food processor programs call methods of
classes that implement this interface. public
class FoodProcessorEnvironment implements
FoodProcessorEnvironmentIF private static
final URL classPath // URL for loading
programs. static try
classPath new URLnew URL("file///bin")
catch (java.net.MalformedURLException
e) throw new
ExceptionInInitializerError(e) // try
// static // Make a slice of food
of the given width. _at_param width The width of the
slice to make. public void slice(int width)
//... // slice(int)
85SP - Dynamic Linkage
// Mix food at the given speed. _at_param
speed The speed to mix at. public void
mix(int speed) //... //
mix(int) // Weight food. _at_return
the wieght in ounces. / public double
weigh() double weight 0.0
//... return weight // weight()
//...
86SP - Dynamic Linkage
// Run named program. _at_param programName
name of the program to run. void run(String
programName) // Create ClassLoader to
load the program classes. When classes are no
longer used, // they can be garbage
collected when their ClassLoader is garbage
collected. URLClassLoader classLoader
new URLClassLoader(classPath) Class
programClass try programClass
classLoader.loadClass(programName)
catch (ClassNotFoundException e) //
Not found //... return
// try
87SP - Dynamic Linkage
AbstractFoodProcessorProgram program try
program (AbstractFoodProcessorProgram)progra
mClass.newInstance() catch (Exception
e) // Unable to run
//... return // try
program.setEnvironment(this)
display(program.getName())
program.start() // run(String)
private void display(String s) //...
// display(String) // class
FoodProcessorEnvironment
88SP - Dynamic Linkage
// Food processor programs call methods of
classes that implement this interface. public
interface FoodProcessorEnvironmentIF //
Make a slice of food of the given width. _at_param
width The width of the slice to make. public
void slice(int width) // Mix food at the
given speed. _at_param speed The speed to mix at.
/ public void mix(int speed) // Weigh
food. _at_return the wieght in ounces. /
public double weigh() //... // interface
FoodProcessorEnvironmentIF
89SP - Virtual Proxy
Synopsis If an object is expensive to
instantiate advantageous to postpone
instantiation until you are sure the object is
needed. Context Various assistants can aid
customers in selection from a catalogue. You
dont want to download every assistant when you
may not even need one.
90SP - Virtual Proxy
Forces Making instances takes time Not
necessary if you do not need them. Solution Prov
ide a service for the top level logic to create
classes on an as needed basis. Consequences
All classes must access the service class, can
cause performance problems.
91SP - Virtual Proxy
Suppose you have the catalogue order system, and
you wish To allow these assistants to help the
orderer with particular Types of products.
Order Product
order
request
assistant
request product request or product request with
assistance
You only want to have the assistant in memory if
you need it.
92SP - Virtual Proxy
uses
Client
ServiceIF
1
uses
Service
ServiceProxy
93SP - Virtual Proxy
// Skeletal example of a service class used by a
virtual proxy. // It implements an interface
written to declare methods rather than the other
way around. public class CabinetAssistant
implements CabinetAssistantIF /
constructor / public CabinetAssistant(Str
ing s) //... // Constructor(String)
//... public void operation1()
//... // operation1() public void
operation2() //... //
operation2() // class CabinetAssistant //
Example of interface implemented by a service
providing class // Declares all of its methods
that a virtual proxy will need to call. public
interface CabinetAssistantIF public void
operation1() public void operation2()
//... // interface CabinetAssistantIF
94SP - Virtual Proxy
import java.lang.reflect.Constructor // This
class is an example of a virtual proxy. public
class CabinetAssistantProxy private
CabinetAssistantIF assistant null private
String myParam // for assistant object's
constructor / Constructor /
public CabinetAssistantProxy(String s)
myParam s // constructor(String) //
Get the CabinetAssistant object used to implement
operations. Creates it if not there. private
CabinetAssistantIF getCabinetAssistant()
if (assistant null) // Get class object that
represents the Assistant class. try
Class clazz Class.forName("CabinetAssistant")
// Get a constructor object to
access the CabinetAssistant class constructor
that // takes a single string
argument. Constructor
constructor
95SP - Virtual Proxy
// Get the constructor object to
create the CabinetAssistant object.
Class formalArgs new Class
String.class constructor
clazz.getConstructor(formalArgs)
// User the constructor object.
Object actuals new Object myParam
assistant (CabinetAssistantIF)constr
uctor.newInstance(actuals) catch
(Exception e) // try
if (assistant null) // deal
with failure to create CabinetAssistant object
throw new RuntimeException()
// if // if return
assistant // getCabinetAssistant()
96SP - Virtual Proxy
//... public void operation1()
getCabinetAssistant().operation1() //
operation1() public void operation2()
getCabinetAssistant().operation2() //
operation2() // class CabinetAssistantProxy
97SP - Decorator AKA Wrapper Pattern
Synopsis Decorator pattern extends the
functionality of an object that is transparent to
its clients. Context Suppose you wish to
control some physical access to a building.
98SP - Decorator
Forces Need to extend functionality of a
class but not through inheritance. Solution Deco
rator pattern provides a service object that
potentially can be extended to implement a common
interface. Consequences Usually fewer
classes but more objects.
99SP - Decorator
Suppose you wish to control some physical devices
such as Access to a building through a security
system.
Provide Access
access
Device
request
You have cameras that monitor the doorway
connected to the access control system. Each
monitor responsible for one camera.
100SP - Decorator
Door ControllerIF
extends
AbstractDoor Controller
DoorController
101SP - Decorator
// This is the superclass of all DoorController
wrappers. abstract class AbstractDoorControllerWra
pper implements DoorControllerIF private
DoorControllerIF wrappee // Constructor
_at_param wrappee DoorController object that this
object delegates to. AbstractDoorControllerWrap
per(DoorControllerIF wrappee)
this.wrappee wrappee //
constructor(wrappee) // Ask door to open if
key is acceptable. _at_param key Data string as key
to open door. public void requestOpen(String
key) wrappee.requestOpen(key) //
requestOpen(String) / close the door
/ public void close()
wrappee.close() // close() //... //
class AbstractDoorControllerWrapper
102SP - Decorator
// All classes that control doors must implement
this interface. interface DoorControllerIF
// Ask the door to open if the given key is
acceptable. _at_param key // A data string
presented as a key to open the door. public
void requestOpen(String key) // close the
door public void close() //... //
interface DoorControllerIF
103SP - Decorator
// Instances are wrapper objects that request a
type A surveillance monitor to dirplay image
class DoorControllerWrapperA extends
AbstractDoorControllerWrapper private
String camera // name of camera that views
this doorway private SurveillanceMonitorIF
monitor // monitor for camera. //
Constructor // _at_param wrappee The
DoorController object that this object will
delegate to. // _at_param camera The name of a
camera that views this door // _at_param monitor
The monitor to ask to view camera's image.
DoorControllerWrapperA(DoorControllerIF wrappee,
String camera,
SurveillanceMonitorIF monitor)
super(wrappee) this.camera camera
this.monitor monitor //
constructor(wrappee)
104SP - Decorator
// Ask door to open if given key acceptable.
_at_param key Data string presented as key public
void requestOpen(String key)
monitor.viewNow(camera)
super.requestOpen(key) //
requestOpen(String) // class DoorControllerWrapp
erA // Objects that control a surveillance
monitor implement this interface. interface
SurveillanceMonitorIF //... // Make
monitor controlled by object show image from
camera. _at_param cameraname void
viewNow(String camera) // interface
SurveillanceMonitorIF