structural patterns adapterdynamic linkage iteratorvirtual proxy bridgedecorator façadecashe...

104
Structural Patterns Adapter Dynamic Linkage Iterator Virtual Proxy Bridge Decorator Façade Cashe Management Flyweight

Upload: dennis-hicks

Post on 12-Jan-2016

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Structural Patterns

Adapter Dynamic Linkage

Iterator Virtual Proxy

Bridge Decorator

Façade Cashe Management

Flyweight

Page 2: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 3: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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 doesn’t implement the interface.

Consequences:

Introduces additional indirection into a program.

SP - Adapter

Page 4: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Filter Array

filteredarray

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.

array

Suppose you want to have a process which filters an array and produces another array

SP - Adapter

Filter Array

filtered array

arrayunf iltered array

Page 5: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Client uses

SP - Adapter

TargetIF

Adaptee uses Adapter

Client

Page 6: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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

SP - Adapter

Page 7: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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(String 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

SP - Adapter

Page 8: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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)

SP - Adapter

Page 9: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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……

SP - Adapter

Page 10: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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;

SP - Adapter

Page 11: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

MenuFrame() { // constructor DRAWING PANEL

super(ResourceManager.getString(ResourceManager.TITLE_MAIN));

createMenus();

addNotify();

Dimension screenSize = getToolkit().getScreenSize();

setSize(screenSize);

drawingPanel = new Panel();

drawingPanel.setBackground(Color.white);

drawingPanel.setForeground(Color.black);

add(drawingPanel, BorderLayout.CENTER);

// Temporary code

drawingPanel.addMouseListener(new TextController(drawingPanel));

} // constructor()

SP - Adapter

Page 12: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// build this frame's menus

private void createMenus() {

String caption;

caption = ResourceManager.getString(ResourceManager.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(ActionEvent evt) { close(); } // actionPerformed

} );

fileMenu.add(exit);

SP - Adapter

Page 13: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

caption = ResourceManager.getString(ResourceManager.ADD);

Menu addMenu = new Menu(caption);

caption = ResourceManager.getString(ResourceManager.TEXT_BOX);

MenuItem textBox = new MenuItem(caption);

addMenu.add(textBox);

caption = ResourceManager.getString(ResourceManager.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);

SP - Adapter

Page 14: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

MenuBar mb = new MenuBar();

mb.add(fileMenu);

mb.add(addMenu);

mb.setHelpMenu(help);

setMenuBar(mb);

} // createMenus()

void showAbout() { // Show this frame’s about dialog

String title;

title = ResourceManager.getString(ResourceManager.TITLE_ABOUT);

String message;

message = ResourceManager.getString(ResourceManager.ABOUT_MESSAGE);

if (aboutDialog == null) {aboutDialog = new AboutDialog(this, title, message); } // if

aboutDialog.show();

} // showAbout()

} // class MenuFrame

SP - Adapter

Page 15: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

import java.awt.*;

import java.awt.event.ActionEvent;

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)

SP - Adapter

Page 16: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 17: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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.

SP - Iterator

Page 18: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

QueryCollection

response

But you do not wish to have to know what the objects are within the collection because you wish to reuse the iterator.

request

You with to browse through a collection.

SP - Iterator

Page 19: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Iterator – Inventory Pattern

InventoryIteratorIF

gets

InventoryItem

InventoryIteratorgets InventoryCollection

InventoryBrowser

displays

Collection

IteratorIF

Iterator

Page 20: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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()

SP - Iterator

Page 21: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

public boolean hasPrevInventoryItem() {

//...

} // hasPrevInventoryItem()

public InventoryItem getPrevInventoryItem() {

//...

} // getPrevInventoryItem()

} // class InventoryIterator

// ...

} // class InventoryCollection/**

// Instances of this class describe an inventory item

SP - Iterator

Page 22: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

public class InventoryItem {

//...

} // class InventoryItem

public interface InventoryIteratorIF {

public boolean hasNextInventoryItem() ;

public InventoryItem getNextInventoryItem() ;

public boolean hasPrevInventoryItem() ;

public InventoryItem getPrevInventoryItem() ;

} // interface InventoryIterator

SP - Iterator

Page 23: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 24: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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 don’t posses any knowledge of the implementation classes.

SP - Bridge

Page 25: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Measure Pounds

poundsDevice1

But you wish to have a reusable common interface for measuring.

scale measurement

Suppose you wish to have some physical devices connectedto the computer and have a common interface for the devices.

SP - Bridge

Measure Speed

mphDevice2 speed measurement

Measure n

#Device3 n measurement

Measure Values

valueDevicen measurement

Page 26: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Bridge – Sensor Example

StreamingSensorSimpleSensor

AveragingSensorAbstraction

I could have this abstraction hierarchy.

Page 27: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Bridge – Sensor Example

With this implementation hierarchy.

HawkSimpleSensor

EagleStreamingSensorEagleSimpleSensor

EagleAveragingSensor

HawkAveragingSensor

HawkStreamingSensor

Page 28: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 29: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Bridge – Sensor Example

SimpleSensorImpl

uses

StreamingSensorImpl

HawkSimpleSensor

EagleStreamingSensor

StreamingSensorSimpleSensor

EagleSimpleSensor

AveragingSensor

AverageSensorImpl

uses

EagleAveragingSensor

uses

HawkAveragingSensor

HawkStreamingSensor

SpecializedAbstraction

AbstractionImpl SpecializedAbstractionImpl

Abstraction

Page 30: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @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.

// @exception SensorException if there is a problem accessing the sensor.

public void beginAverage() throws SensorException {

((AveragingSensorImpl)getImpl()).beginAverage();

} // beginAverage()

} // class AveragingSensor

SP - Bridge

Page 31: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @exception SensorException if there is a problem accessing the sensor.

public void beginAverage() throws SensorException;

} // interface AveragingSensorImpl

SP - Bridge

Page 32: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

//* 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.

// @exception SensorException if there is a problem accessing the sensor.

public void beginAverage() throws SensorException {

//...

} // beginAverage()

} // class EagleAveragingSensor

SP - Bridge

Page 33: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// This class implements SimpleSensor operations for sensors made by Eagle.

class EagleSimpleSensor implements SimpleSensorImpl {

// Return the value of the sensor's current measurement.

// @exception SensorException if there is a problem accessing the sensor.

public int getValue() throws SensorException {

int value;

//...

return value;

} // getValue()

} // class EagleSimpleSensor

SP - Bridge

Page 34: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @param freq Max times per minute this streaming sensor produces a measurement

// This class impelments StreamingSensor operations for sensors made by Eagle.

public void setSamplingFrequency(int freq) throws SensorException {

//...

} // setSamplingFrequency(int)

SP - Bridge

Page 35: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

//* @param abstraction The abstraction object to deliver measurement values to.

public void setStreamingSensorListener(StreamingSensorListener listener) {

//...

} // setStreamingSensorListener(StreamingSensorListener)

} // class EagleStreamingSensor

SP - Bridge

Page 36: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @exception SensorException if there is a problem accessing the sensor.

public void beginAverage() throws SensorException {

//...

} // beginAverage()

} // class HawkAveragingSensor

SP - Bridge

Page 37: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @param freq The maxnumber of times per minute streaming sensor produces a value

// @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.

// @param abstraction The abstraction object to deliver measurement values to.

public void setStreamingSensorListener(StreamingSensorListener listener) {

//...

} // setStreamingSensorListener(StreamingSensorListener)

} // class HawkStreamingSensor

SP - Bridge

Page 38: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Instances are thrown by methods that access sensors when they encounter an error

public class SensorException extends Exception {

// Constructor @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.

// @param impl Object that implements ensor type-specific operations this object provides

SP - Bridge

Page 39: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SimpleSensor(SimpleSensorImpl impl) { this.impl = impl; } // constructor(SimpleSensorImpl)

// 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.

// @exception SensorException if there is a problem accessing the sensor.

public int getValue() throws SensorException { return impl.getValue(); } // getValue()

} // class SimpleSensor

SP - Bridge

Page 40: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// All objects that implement operations for SimpleSensor objects must

// implement this interface.

interface SimpleSensorImpl {

// Return the value of the sensor's current measurement.

// @exception SensorException if there is a problem accessing the sensor.

public int getValue() throws SensorException;

} // interface SimpleSensorImpl

SP - Bridge

Page 41: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.PipedInputStream;

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

SP - Bridge

Page 42: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @param impl Object implements sensor type-specific operations this object will provide.

// @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;

SP - Bridge

Page 43: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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)

//...

SP - Bridge

Page 44: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Streaming sensors produce a stream of measurement values.

// The stream of values produced with frequency no greater than given numberper minute.

// @param freq The max times per minute that streaming sensor produces a value.

// @exception SensorException if there is a problem accessing the sensor.

//

public void setSamplingFrequency(int freq) throws SensorException {

// delegate this to the implementation object

((StreamingSensorImpl)getImpl()).setSamplingFrequency(freq);

} // setSamplingFrequency(int)

SP - Bridge

Page 45: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @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)

SP - Bridge

Page 46: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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

removeStreamingSensorListener(StreamingSensorListener listener) {

listeners.removeElement(listener);

} // addStreamingSensorListener(StreamingSensorListener)

SP - Bridge

Page 47: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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 i=0; i < listeners.size(); i++) {

StreamingSensorListener listener;

listener = (StreamingSensorListener)listeners.elementAt(i);

listener.processMeasurement(value);

} // for

} // while

} // run()

} // class StreamingSensor

SP - Bridge

Page 48: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @param freq The max times per minute that streaming sensor produces a value.

// @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.

//* @param abstraction The abstraction object to deliver measurement values to.

public void setStreamingSensorListener(StreamingSensorListener listener);

} // interface StreamingSensorImpl

SP - Bridge

Page 49: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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.

// @param value The measurement value being delivered.

public void processMeasurement(int value);

} // interface StreamingSensorListener

SP - Bridge

Page 50: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 51: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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 don’t need to know about any of the classes behind the façade.

Page 52: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

CreateE-mail

message

SP - Facade

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).

information

You wish to perform a function that involves many classeswith dependencies that add complexity.

SendE-mail

sent e-mail

Page 53: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Façade - Mail Example

Attachment

MessageSender

MessageBody

MessageHeader

Client creates

contains

createscreates

creates

Security

Message

creates

contains

sends

contains

Page 54: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Façade – Reusable example

Attachment

MessageSender

MessageBody

MessageHeader

MessageCreatercreates

contains

createscreates

creates

Security

Message

creates

contains

sends

contains

Clients

uses

Page 55: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Façade

Facade

Clients

uses

Page 56: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facade/ Instances of this class encapsulate message attachments

class Attachment {

// Constructor @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 @param header message header. * @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

Page 57: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facade// Instances of this class encapsulate the messge body for an e-mail message.

class MessageBody {

// * Constructor * @param body the content of the message body

MessageBody(RichText body) {

//...

} // Constructor(RichText)

// Add attachment to this message body.* @param attachment object to add tomessage.

void addAttachment(Attachment attachment) {

//...

} // addAttachment(Attachment)

} // class MessageBody

Page 58: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facadeimport 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;

Page 59: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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

// * @param to The address that this object will send a message to.

// * @param from The address that the message will say it is from.

// * @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)

Page 60: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

// * @param to The address that this object will send a message to.

// * @param from The address that the message will say it is from.

// * @param subject The subject of this message.

// * @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)

Page 61: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facade // Set contents of message body. @param messageBody contents of the message body.

public void setMessageBody(String messageBody) {

setMessageBody(new RichTextString(messageBody));

} // setMessageBody(String)

// Set contents of contents body. @param messageBody contents of the message body.

public void setMessageBody(RichText messageBody) {

this.messageBody = messageBody;

} // setMessageBody(RichText)

// Add an attachement to message @param attachment object to attach to message

public void addAttachment(Object attachment) {

attachments.addElement(attachment);

} // addAttachment(Object)

// set whether this message should be signed. The default is false.

public void setSignMessage(boolean signFlag) {

signMessage = signFlag;

} // setSignMessage(boolean)

Page 62: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facade// * Set the value of a header field. @param name The name of the field to set the value of

// * @param value The value to set the field to.

public void setHeaderField(String name, String value) {

headerFields.put(name.toLowerCase(), value);

} // setHeaderField(String, String)

// Send the message.

public void send() {

MessageBody body = new MessageBody(messageBody);

for (int i = 0; i < attachments.size(); i++) {

body.addAttachment(new Attachment(attachments.elementAt(i)));

} // for

MessageHeader header = new MessageHeader(headerFields);

Message msg = new Message(header, body);

if (signMessage) { msg.setSecurity(createSecurity()); } // if

createMessageSender(msg);

} // send()

Page 63: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facade // Infer an message type from a destination e-mail address. @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

Page 64: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - Facadeimport java.util.Hashtable;

/**

* Instances of this class encapsulate header information.

*/

class MessageHeader {

/**

* constructor

* @param fields A Hashtable that contains the field values for this

* header.

*/

MessageHeader(Hashtable fields) {

//...

} // constructor(Hashtable)

//...

} // class MessageHeader

Page 65: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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 @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

Page 66: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 67: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

ProcessElements

stream Word Doc

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.

document element

Suppose you wish to write a word processor such as WORD.

SP - Flyweight

Page 68: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Document Applicationedits 1

*

MyDocument May be doc, xls, or ppt.

SP - Flyweight

Page 69: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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 * @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()

SP - Flyweight

Page 70: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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

SP - Flyweight

Page 71: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Return DocChar object representing given character. @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

SP - Flyweight

Page 72: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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. @param c

public void setChar(char c) { character = c; } // setChar(char)

} // class MutableDocChar

} // class DocCharFactory

SP - Flyweight

Page 73: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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 object’s font inherited through container

private Font font;

DocumentContainer parent; // this object's container

// Return child object at the given position. * @param index The index of the child.

public DocumentElement getChild(int index) {

return (DocumentElement)children.elementAt(index);

} // getChild(int)

SP - Flyweight

Page 74: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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(DocumentElement)

SP - Flyweight

Page 75: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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. @param font The font to associate with this object

public void setFont(Font font) {

this.font = font;

} // setFont(Font)

//...

} // class DocumentContainer

SP - Flyweight

Page 76: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management 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

SP - Flyweight

Page 77: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 78: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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.

SP - Dynamic Linkage

Page 79: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Process Food

processedfood Productfoodtype

We wish to have a food processor To process particular food in a certain way.

SP - Dynamic Linkage

Page 80: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

FoodProcessorEnvironmentIF

AbstractFoodProcessorProgram

uses 1

*

FoodProcessorEnvironment

EnviornmentIF

SP - Dynamic Linkage

ConcreteFoodProcessorProgram

uses

Enviornment

AbstractLoadableClass

ConcreteLoadableClass

Page 81: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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(FoodProcessorEnvironmentIF)

SP - Dynamic Linkage

Page 82: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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

SP - Dynamic Linkage

Page 83: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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 > 120.0 && weight < 160.0) getEnvironment().mix(4);

//...

} // start()

//...

} // class ConcreteFoodProcessorProgram

SP - Dynamic Linkage

Page 84: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

import java.net.URL;

import java.net.URLClassLoader;

// 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 URL[]{new URL("file:///bin")}; }

catch (java.net.MalformedURLException e)

{ throw new ExceptionInInitializerError(e);

} // try

} // static

// Make a slice of food of the given width. @param width The width of the slice to make.

public void slice(int width) {

//...

} // slice(int)

SP - Dynamic Linkage

Page 85: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// * Mix food at the given speed. * @param speed The speed to mix at.

public void mix(int speed) {

//...

} // mix(int)

// * Weight food. * @return the wieght in ounces. */

public double weigh() {

double weight = 0.0;

//...

return weight;

} // weight()

//...

SP - Dynamic Linkage

Page 86: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Run named program. * @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

SP - Dynamic Linkage

Page 87: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

AbstractFoodProcessorProgram program;

try { program = (AbstractFoodProcessorProgram)programClass.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

SP - Dynamic Linkage

Page 88: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Food processor programs call methods of classes that implement this interface.

public interface FoodProcessorEnvironmentIF {

// Make a slice of food of the given width. @param width The width of the slice to make.

public void slice(int width) ;

// Mix food at the given speed. @param speed The speed to mix at. */

public void mix(int speed) ;

// Weigh food. @return the wieght in ounces. */

public double weigh() ;

//...

} // interface FoodProcessorEnvironmentIF

SP - Dynamic Linkage

Page 89: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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 don’t want to download every assistant when you may not even need one.

Page 90: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Forces:

Making instances takes time

Not necessary if you do not need them.

Solution:

Provide 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.

SP - Virtual Proxy

Page 91: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

You only want to have the assistant in memory if you need it.

Suppose you have the catalogue order system, and you wish To allow these assistants to help the orderer with particular Types of products.

OrderProduct

orderrequest

SP - Virtual Proxy

request = product request or product request with assistance

assistant

Page 92: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Client ServiceIFuses 1

*

ServiceProxy

SP - Virtual Proxy

Service

uses

Page 93: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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(String 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

SP - Virtual Proxy

Page 94: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

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;

SP - Virtual Proxy

Page 95: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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)constructor.newInstance(actuals);

} catch (Exception e) {

} // try

if (assistant == null) {

// deal with failure to create CabinetAssistant object

throw new RuntimeException();

} // if

} // if

return assistant;

} // getCabinetAssistant()

SP - Virtual Proxy

Page 96: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

//...

public void operation1() {

getCabinetAssistant().operation1();

} // operation1()

public void operation2() {

getCabinetAssistant().operation2();

} // operation2()

} // class CabinetAssistantProxy

SP - Virtual Proxy

Page 97: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

SP - 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.

Page 98: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

Forces:

Need to extend functionality of a class but not through inheritance.

Solution:

Decorator pattern provides a service object that potentially can be extended to implement a common interface.

Consequences:

Usually fewer classes but more objects.

SP - Decorator

Page 99: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

ProvideAccess

access Device

You have cameras that monitor the doorway connected to the access control system. Each monitor responsible for one camera.

request

Suppose you wish to control some physical devices such as Access to a building through a security system.

SP - Decorator

Page 100: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

DoorControllerIF

DoorController

extends

AbstractDoorController

SP - Decorator

Page 101: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// This is the superclass of all DoorController wrappers.

abstract class AbstractDoorControllerWrapper implements DoorControllerIF {

private DoorControllerIF wrappee;

// Constructor @param wrappee DoorController object that this object delegates to.

AbstractDoorControllerWrapper(DoorControllerIF wrappee) {

this.wrappee = wrappee;

} // constructor(wrappee)

// Ask door to open if key is acceptable. @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

SP - Decorator

Page 102: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// All classes that control doors must implement this interface.

interface DoorControllerIF {

// Ask the door to open if the given key is acceptable. @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

SP - Decorator

Page 103: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// 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

// @param wrappee The DoorController object that this object will delegate to.

// @param camera The name of a camera that views this door

// @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)

SP - Decorator

Page 104: Structural Patterns AdapterDynamic Linkage IteratorVirtual Proxy BridgeDecorator FaçadeCashe Management Flyweight

// Ask door to open if given key acceptable. @param key Data string presented as key

public void requestOpen(String key) {

monitor.viewNow(camera);

super.requestOpen(key);

} // requestOpen(String)

} // class DoorControllerWrapperA

// Objects that control a surveillance monitor implement this interface.

interface SurveillanceMonitorIF {

//...

// Make monitor controlled by object show image from camera. @param cameraname

void viewNow(String camera) ;

} // interface SurveillanceMonitorIF

SP - Decorator