Additional Examples • Creational – Factory method – Abstract factory • Structural – Decorator – Adapter • Behavioral – Observer

Design Patterns--Factory Method • Intent--Permit a class to be reuseable with arbitrary data types. Specifically, allow the class to be independent of the classes it instantiates – Define an for object creation. – Let subclasses decide which class to instantiate. • Motivation – Useful for development of frameworks

1 Factory Method--Continued

• Consider a document-processing framework – High-level support for creating, opening, saving documents – Consistent method calls for these commands, regardless of document type (word-processor, spreadsheet, etc.) – Logic to implement these commands delegated to specific types of document objects. – May be some operations common to all document types.

Factory Method--Continued Document Processing Example-General Framework:

Document Application getTitle( ) * Edits 1 newDocument( ) newDocument( ) openDocument( ) openDocument( ) ......

MyDocument Problem: How can an Application object newDocument( ) create instances of specific document classes openDocument( ) without being application-specific itself. ...

2 Factory Method--Continued Use of a document creation “factory”: Document Application getTitle( ) * Edits 1 newDocument( ) newDocument( ) openDocument( ) openDocument( ) ...... 1 requestor * Requests-creation creator 1 <> MyDocument DocumentFactoryIF newDocument( ) createDocument(type:String):Document openDocument( ) ...

DocumentFactory creates 1 createDocument(type:String):Document

The

Product Uses CreationRequestor * 1 Operation1( ) newDocument( ) Operation2( ) ... … 1 requestor * Requests-creation creator 1 ConcreteProduct <> Operation1( ) FactoryIF Operation2( ) createProduct(discriminator):Product …

Creates Factory 1 createProduct(discriminator):Product

3 Factory Example--Encrypted Sockets Socket Encryption * Encrypts-and-decrypts-bytes encryptor/decryptor 1 encrypedOutputStream( ) byte source decrypedInputStream( ) EncryptedSocket <> encryptedSocket(key, EncryptionFacoryIF) <> DESencryption RSAencryption getInputStream( ) getOutputStream( ) * * 1 requestor Requests-creation * creator <> EncryptionFactoryIF createEncryption(key):Encryption Creates

Creates 1 EncryptionFactory 1 createEncryption(key):Encryption

Factory Example--Java Implementation import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.security.Key; import java.security.NoSuchAlgorithmException; /** * This class extends socket so that the stream of bytes that goes over the net is encrypted. */ public class EncryptedSocket extends Socket { private static Encryption crypt; private Key key; /** * Constructor * @param key The key to use for encryption and decryption. This object will determine the * encryption technique to use by calling the key object's getAlgorithm() method. * @param factory The Factory object to use to create Encryption * objects. * @exception NoSuchAlgorithmException if the key specifies an encryption technique that * is not available. */

4 Java Implementation--Continued public EncryptedSocket(Key key, EncryptionFactoryIF factory) throws NoSuchAlgorithmException { this.key = key; crypt = factory.createEncryption(key); } // Constructor(Key, EncryptionFactoryIF) /** * Returns an input stream for this socket that decrypts the inbound stream of bytes. * * @return an input stream for reading decrypted bytes from this socket. * @exception IOException if an I/O error occurs when creating the input stream. */ public InputStream getInputStream() throws IOException { return crypt.decryptInputStream(super.getInputStream()); } // getInputStream() /** * Returns an output stream for this socket that encrypts theoutbound stream of bytes. * * @return an output stream for reading decrypted bytes from this socket. * @exception IOException if an I/O error occurs when creating the output stream. */ public OutputStream getOutputStream() throws IOException { return crypt.encryptOutputStream(super.getOutputStream()); } // getOutputStream() } // class EncryptedSocket

Java Implementation--Continued

import java.security.Key; import java.security.NoSuchAlgorithmException;

/** * This interface must be implemented by all factory classes used to create instances of * subclasses of Encryption. */ public interface EncryptionFactoryIF { /** * This method returns an instance of the appropriate subclass of Encryption as determined * from information provided by the given Key object. * @param key The key that will be used to perform the encryption. */ public Encryption createEncryption(Key key) throws NoSuchAlgorithmException; } // interface EncryptionFactoryIF

5 Java Implementation--Continued

/** * This class creates instances of appropriate subclasses of Encryption. * The appropriate subclass is determined by calling the Key object's */ public class EncryptionFactory implements EncryptionFactoryIF { /** * This method returns an instnace of the appropriate subclass of Encryption as determined * from information provided by the given Key object's getAlgorithm method. * @param key The key that will be used to perform the encryption. */ public Encryption createEncryption(Key key) throws NoSuchAlgorithmException{ String algorithm = key.getAlgorithm(); if ("DES".equals(algorithm)) return new DESEncryption(key); if ("RSA".equals(algorithm)) return new RSAEncryption(key); throw new NoSuchAlgorithmException(algorithm); } // createEncryption(Key) } // class EncryptionFactory

Java Implementation--Continued

/** /** * Abstract class to encrypt/decrypt * This method returns an OutputStream that * streams of bytes. * encrypts the bytes written to it and writes */ * the encrypted bytes to the given OutputStream. abstract public class Encryption { * @param out The OutputStream that the private Key key; * OutputStream returned by this method /** * will write encrypted bytes to. * Constructor */ * @param key The key to use to perform abstract OutputStream encryptOutputStream * the encryption. (OutputStream out); */ /** public Encryption(Key key) { * This method returns an InputStream that this.key = key; * decrypts the stream of bytes that it reads from } // Constructor(Key) * the given InputStream. * @param in The InputStream that the /** * InputStream returned by this * Return the key this object used for * method will read bytes from. * encryption and decryption. */ */ abstract InputStream decryptInputStream protected Key getKey() { (InputStream in); return key; } // class Encrypt } // getKey()

6 A More Streamlined Version of Factory Method

uses Creator … Product FactoryMethod( ) product=FactoryMethod( ) AnOperation( ) ...

creates ConcreteCreator ConcreteProduct FactoryMethod( ) return new ConcreteProduct

The • Intent: – Provide an interface for creating families of related or dependent objects without specifying their concrete classes • Also Known as: – kit – toolkit

7 Abstract Factory Pattern-- Motivation

uses WidgetFactory Client CreateScrollBar( ) Window CreateWindow( ) uses

PMWindow MotifWindow

MotifWidgetFactory creates PMWidgetFactory uses CreateScrollBar( ) CreateScrollBar( ) ScrollBar CreateWindow( ) CreateWindow( )

creates PMScrollBar MotifScrollBar creates creates

Abstract Factory Pattern Structure

uses AbstractFactory Client CreateProductA( ) AbstractProductA CreateProductB( ) uses

ProductA2 ProductA1 creates ConcreteFactory1 ConcreteFactory2 uses CreateProductA( ) CreateProductA( ) AbstractProductB CreateProductB( ) CreateProductB( )

creates ProductB2 ProductB1 creates creates

8 Structural Patterns--Decorator • Intent – Extend the functionality of an object without subclassing. – Allow object functionality to be extended and restricted dynamically. • Also known as – wrapper pattern

Decorator Pattern Example • Consider a TextView object – displays text in a window – no scroll bars – no border • Want to be able to extend text view to permit scrollbars and borders • Don’t want to use inheritance to extend functionality of TextView. • Solution: Use composition of Textview object with “decorator” objects

9 Decorator Example--Continued

Visual Component 1 Draw( ) ... component

TextView Decorator 1 Draw( ) Draw( ) component.Draw( )

ScrollDecorator BorderDecorator

ScrollPosition BorderWidth super.Draw( ) Draw( ) Draw( ) DrawBorder( ) ScrollTo( ) DrawBorder( )

Decorator Pattern--General Structure

AbstractComponent 1 Operation( ) ... component

ConcreteComponent AbstractDecorator 1 Operation( ) Operation( ) component.Operation( )

ConcreteDecoratorA ConcreteDecoratorB

AddedState AddedState super.Operation( ) Operation( ) Operation( ) AddedBehavior( ) AddedBehavior( ) AddedBehavior( )

10 Decorator Pattern--Java Code Example abstract class VisualComponent( ) { public void Draw( ); public void Resize( ); … } // class VisualComponent

abstract class Decorator extends VisualComponent { private VisualComponent component; public Decorator (VisualComponent comp) { this.component = comp; } // constructor public Draw( ) { component.Draw( ); } // Draw public Resize( ) { component.resize( ); }// Resize ... }// class Decorator

Decorator Example--Continued

class BorderDecorator extends Decorator { private int width;

public BorderDecorator(VisualComponent comp, int BorderWidth) { super(comp); // call constructor of parent class this.width = BorderWidth; } // Constructor

private void DrawBorder { … // code to implement Draw Border method } // DrawBorder

public Draw( ) { super.Draw( ); DrawBorder(width); } // Draw

11 Decorator Pattern Code--Continued class ScrollDecorator extends Decorator { private int position = 0;

public ScrollDecorator(VisualComponent comp) { super(comp); // call constructor of parent class } // Constructor

private void ScrollTo(int newposition) { … // code to implement ScrollTo method } // ScrollTo

private void DrawScroll( ) { … // code to implement DrawScroll method } // DrawScroll

public Draw( ) { super.Draw( ); DrawScroll; } // Draw

Decorator Pattern Code--Continued

Now we can create a text object with scroll bar and border as follows:

TextView text = new TextView(); ScrollDecorator stext = new ScrollDecorator(text); VisualComponent bstext = new BorderDecorator(stext);

12 Decorator Pattern Example--Object Composition

bstext stext

delegates text Draw Draw delegates Draw DrawBorder DrawScroll

ScrollTo(x) (Note that client would require knowledge of the stext object

Structural Pattern--Adapter

• Intent: Translates between an interface expected by clients and the interface of otherwise incompatible objects. • Motivation: – allows classes to work together that otherwise couldn’t – permits you to use an existing class that doesn’t have the interface that you need.

13 --General Structure Class Adapter: <> Adaptee Client Target Request( ) SpecificRequest( )

Adapter Request( ) SpecificRequest( ) Object Adapter: <> Client Target Adaptee Request( ) SpecificRequest( )

adaptee Adapter Request( ) adaptee.SpecificRequest( )

Behavioral Patterns--Observer • Intent--Allow multiple dependent objects to be notified when the state of an object changes. • Also known as: publisher-subscriber

14 --General Structure

Subject observed by Observer Attach(observer) 1 * Update( ) Detach(observer) Notify( ) for all o in observers { o.Update( ) }

ConcreteSubject subject ConcreteObserver subjectState observerState GetState( ) return SubjectState Update( ) SetState( )

observerState = subject.GetState( )

Observer--Use of a Multicaster

Registers <> <> (to receive notifications) 0..* 1 ObservableIF ObserverIF addObserver(:ObserverIF) Update( ) 0..* removeObserver(:ObserverIF)

Notifies

Observable Observer 1 1 Registers-observers Notifies 1 1 Multicaster addObserver(:ObserverIF) removeObserver(:ObserverIF)

15 Observer and Adapter Pattern Example--The Java Event Model • Indirect coupling between an object that fields an event and other objects interested in the event (listeners) • based on the observer pattern • An observed component needs no knowledge about the number and structure of listeners • Such loose coupling creates a plug-n-play architecture capability

Java Events • Public methods and events are used for communication with the outside world • Strong typing is enforced through interface classes which must be implemented by both the observed (alternatively the multicaster) and observer • Examples from the Advanced Windowing Tool Kit (AWT) – Listener interfaces and adapters

16 More about Java Events

• Events are a class hierarchy • Events are not usually changed as they are passed between objects • Events have public attributes and operations used for its interpretation by a listener • Synchronization can cause deadlocks if the observed object holds locks

java.awt.event Events

ActionEvent ContainerEvent

AdjustmentEvent FocusEvent

KeyEvent

AWTEvent Abstract ComponentEvent Java.awt-events InputEvent

MouseEvent

itemEvent PaintEvent

TextEvent WindowEvent

17 java.awt.event Listener Interfaces

Interface ActionListener

Interface AdjustmentListener

Interface abstract CoomponentListener ComponentAdapter

Interface abstract ContainerListener ContainerAdapter Interface EventListener abstract java.util FocusListener FocusAdapter

Interface ItemListener

Interface abstract KeyListener KeyAdapter

Interface abstract MouseListener MouseListenerAdapter Interface MouseMotionListener abstract Interface MouseMotionAdapter TextListener

Interface abstract WindowListener WindowAdapter

Graphical User Interface Example

This string is an attribute of textField

java.awt.textField java.awt.button

18 Sends Event to Every Added Listener

AWTEventMulticaster Interface ActionListener ActionPerformed(); ActionPerformed(); Implements Add(); Remove();

Add Remove multicaster Implements ActionPerformed ->Add(l);

ZapTextField Button AddActionListener(ActionListoner l); AddActionListener ActionPerformed(); performActionEvent(ACtionEvent e);

Multicaster looks like an ActionListener Object giving: actionListener.ActionPerformed(e);

Object

TextField

Component

Attribute: String text TextComponent int columns char EchoChar

Methods: Methods: int getCaretPosition(); synchronized void addActionListener(ActionListener l); synchronized boolean echoCharIsSet(); getSelectedText(); int getColumns(); sychronized in char getEchoChar(); getSelectionEnd(); Dimension getMinimumSize(); setText(String t). synchronized void

.... removeActionListener(ActionListener l); void setColumns(int Columns); void setEchoChar(char C); protected void processActionEvent(ActionEvent e); protected void processEvent(AWTEvent e);

19 Component

Methods: synchronized void addMouseListener(MouseListener l); protected void processMouseEvent(MouseEvent e); protected void processMouseMotionEvent(MouseMotionEvent e); ... public boolean IsEnabled();

Button

Attributes: string label; Methods: String getLabel(); synchronized void setLabel(String label); synchronized void addActionListener(ActionListener l); ...

Button Attaches Observer

Adds the specified action listener to receive action events from this button. Action events occur when a user presses or releases the mouse over this button. public synchronized void addActionListener(ActionListener l) { actionListener = AWTEventMulticaster.add(actionListener, l); }

20 Button Sends Action Event to all Observers

protected void processActionEvent(ActionEvent e) { if (actionListener != null) { actionListener.actionPerformed(e); } }

Extended Text Field as an Observer

public class ZapTextField extends TextField implements ActionListener { public ZapTextField() {attachButton();} protected void attachButton() { button1.addActionListener(this); } public void actionPerformed(ActionEvent e) { this.setText(”~~~~~~~~~"); } }

21 Adapters in Java API

• Adapters are implemented as classes with stubbed methods • Classes using the adapter extend only those stubbed methods that they need. • Without the use of an adapter, a class that implements and interface would have to implement all of the methods in that interface, even if it isn’t interested in all of them.

Mouse Adapter

Interface MouseListener

public abstract void mouseclicked(MouseEvent e); public abstract void mouseEntered(MouseEvent e); public abstract void mouseExited(MouseEvent e); public abstract void mousePressed(MouseEvent e); public abstract void mouseReleased(MouseEvent e);

Implements

MouseAdapter

public void mouseclicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {}

Extends

Button public void mouseclicked(MouseEvent e) { ... }

22 Use of Adapters in the Java API

Event Handling using an anonymous inner class:

Button pushMe = new Button(“Push Me”) pushMe.addActionListener(new ActionListener( ) { public void actionPerformed(actionEvent evt) { doSomethingFantastic(ActionEvent) } // actionPerformed(ActionEvent) } ); add (pushMe); . . .

Note: The Java API contains a number of abstract adapter classes-- e.g. WindowAdapter in AWT (InternalFrameAdapter in Swing). Look at the Java API Specification and determine the purpose of these adapters.

23