0% found this document useful (0 votes)
107 views

Design Patterns: Horstmann Chapter 5 (Sections 1-7)

The document discusses design patterns and how they provide reusable solutions to common programming problems. It specifically covers the Iterator pattern, which allows accessing elements of an aggregate object sequentially without exposing its underlying structure. The Iterator pattern provides a standard interface for traversing elements with methods like hasNext() and next() that return the next element. This pattern allows multiple iterators to independently traverse the same aggregate object simultaneously.

Uploaded by

ben simanjuntak
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
107 views

Design Patterns: Horstmann Chapter 5 (Sections 1-7)

The document discusses design patterns and how they provide reusable solutions to common programming problems. It specifically covers the Iterator pattern, which allows accessing elements of an aggregate object sequentially without exposing its underlying structure. The Iterator pattern provides a standard interface for traversing elements with methods like hasNext() and next() that return the next element. This pattern allows multiple iterators to independently traverse the same aggregate object simultaneously.

Uploaded by

ben simanjuntak
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Design Patterns

• In object-oriented development, Design Patterns are solutions


that developers have refined over time to solve a range of recurring
Design Patterns (and some GUI Programming) design problems.

Horstmann Chapter 5 (sections 1-7) • A design pattern has four elements

✦A name that uniquely identifies the pattern from other patterns.

Unit 5

✦A problem description that describes the situation in which the pattern


CS 3354

Spring 2017
can be used.

✦A solution stated as a set of collaborating classes and interfaces.

Jill Seaman
✦A set of consequences that describes the trade-offs and alternatives to
be considered with respect to the design goals being addressed.

1 2

Design Patterns Delegation

• The following terms are often used to denote the classes that • Delegation: A special form of aggregation, commonly used in
collaborate in a design pattern:
design patterns.

✦The client class accesses the pattern classes.


✦One class (A) contains a reference to another (B) (via member variable)

✦The pattern interface is the part of the pattern that is visible to the client ✦A implements its operations/methods by calling methods on B. 

class (might be an interface or abstract class).
(Methods may have different names)

✦The implementor class provides low level behavior of the pattern. Often ✦Makes explicit the dependencies between A and B.
the pattern contains many of these.

• Advantages of delegation:

✦The extender class specializes an implementor class to provide different


implementation of the pattern. These usually represent future classes ✦B might be a pre-existing class, so we can reuse it without changing it.

anticipated by the developer.


✦B is hidden from clients of A, B can easily be changed or even replaced
• Common tradeoff: Simple architecture vs extensibility with another class.

3 4
Encapsulating Traversals with
The ITERATOR Pattern Compare to C++ linked list traversal
• Recall using an Iterator to iterate through the elements of a linked • Recall performing a traversal of a linked list in C++:

list in Java:

LinkedList<String> countries = new LinkedList<String>(); ListNode *p = head;


countries.add("Belgium");
 while (p!=NULL) {
countries.add("Italy");
 cout << p->value << “ “;
countries.add("Thailand"); p = p->next;
Iterator<String> iterator = countries.iterator();
 }
while (iterator.hasNext()) {
 cout << endl;
String country = iterator.next();

System.out.println(country);
}
• This exposes the internal structure of the list.

• The hasNext method tests whether the iterator is at the end of the • And it’s error-prone: “it is very easy to mess up links and corrupt
list.
the link structure of a linked list”
• The next method returns the current element and advances the
iterator to the next position.

• Why does the Java library use an iterator to traverse a linked list?
5 6

What interface (methods) to use instead? A Cursor-based Linked List


• For a (java) Queue:
• A common linked-list implementation is a list with a cursor

void add(E x) //enqueue


E remove() //dequeue • A list cursor marks a position similar to the cursor in a word
E peek() //returns next elem (doesn’t remove) processor.

int size() //number of elems in the queue


E getCurrent() // Get element at cursor
void set(E x) // Set element at cursor to x
E remove() // Remove element at cursor
• For an Array List:
void insert(E x) // Insert x before cursor
E get(int i) void reset() // Reset cursor to head
void set(int i, E x) void next() // Advance cursor Note: next() does not
void add(E x) boolean hasNext() // Check if cursor can be advanced return anything
int size()
• Requires adding a field to point to the current element.

• For a Linked List, we want to be able to add and remove elements • Here is how to traverse the list:
from the middle of the list, but it would be very inefficient to specify list.reset();
a position in a linked list with an integer index. while (list.hasNext()) {
//do something with list.getCurrent();
list.next();
}
7 8
Problem with the Cursor-based Linked List The Iterator as a Design Pattern
• There is only one cursor, you can’t implement algorithms that Name: Iterator Design Pattern

compare different list elements.
Problem Description: Provide a way to access the elements of an aggregate
object sequentially without exposing its underlying representation, for multiple
• You can’t even print the contents of the list for debugging clients simultaneously.

purposes, because it moves the cursor to the end.
Solution: ConcreteIterator class implements the Iterator interface for
accessing and traversing elements. The ConcreteAggregate implements the
Aggregate interface for creating an Iterator object.
• In Java, a List<T> can have any number of iterators attached to it.

• The iterator concept is also useful outside of the collection classes


(see the Scanner).
Note: there is no reset(),
use createIterator() to
get a new one.

• It is a good solution to a common problem.


createIterator() returns
an iterator with cursor
on the first element.

9 10

Encapsulating Legacy Components with the


Example: Linked List Iterators ADAPTER Pattern
• I substituted the Java types from the Linked List example into the Name: Adapter Design Pattern

class diagram to show how it fits the pattern.
Problem Description: Convert the interface of a legacy class into a different
interface expected by the client, so they can work together without changes. 

Solution: Adapter class implements the Target interface expected by the
next() is equivalent to: client. The Adapter delegates requests from the client to the Adaptee (the pre-
x=getCurrent(); existing legacy class) and performs any necessary conversion.
advance cursor;
return x;

LinkedList<String> countries = new LinkedList<String>();


countries.add("Belgium");

countries.add("Italy");

countries.add("Thailand");
Iterator<String> iterator = countries.iterator();

while (iterator.hasNext()) {

String country = iterator.next();

System.out.println(country);
} 11 12
Example: Adding an Icon to a UI Container Example: Adding an Icon to a UI Container
• First, how to display a window and add UI Components to it:
• First, construct some buttons:

JButton helloButton = new JButton("Say Hello");


• A frame window is a top-level window, usually decorated with JButton goodbyeButton = new JButton("Say Goodbye");
borders and a title bar, displayed as follows:

• Make a text field:

JFrame frame = new JFrame();
 final int FIELD_WIDTH = 20;


frame.pack();
 JTextField textField = new JTextField(FIELD_WIDTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 textField.setText("Click a button!”);
frame.setVisible(true);
• Set a layout manager (how to position components):

• pack: sets the size of the frame to the smallest size needed to
display its components.
frame.setLayout(new FlowLayout());

• EXIT_ON_CLOSE: program exits when user closes the window.


• Finally, add the components to the frame and display.

frame.add(helloButton);
• Let’s build this:
frame.add(goodbyeButton);
frame.add(textField);
frame.pack();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

13 14

Example: Adding an Icon to a UI Container Example: IconAdapter


• NOW, let’s say I want to add a MarsIcon to my JFrame.
import java.awt.*;
import javax.swing.*;
• Problem: the JFrame.add() method takes a Component, not an /**
Icon.
An adapter that turns an icon into a JComponent.
*/
• I could just make my MarsIcon implement the Component interface, public class IconAdapter extends JComponent
{
but that’s a lot of work.
public IconAdapter(Icon icon) {
this.icon = icon;
• There is a JComponent class that I could make MarsIcon inherit }
from, but let’s assume MarsIcon already has another superclass.
public void paintComponent(Graphics g) {
icon.paintIcon(this, g, 0, 0);
• Solution: Make a new class (IconAdapter) that is a subclass of }
public Dimension getPreferredSize() {
JComponent. It will hold a reference to an Icon. It translates return new Dimension(icon.getIconWidth(),
JComponent methods to Icon methods.
icon.getIconHeight());
}
private Icon icon;
}

15 16
Example: IconAdapterTester Adapter Pattern: IconAdapter

• The IconAdapter as an instance of the ADAPTER Pattern.

import java.awt.*;
import javax.swing.*; • Note we use inheritance instead of implementing an interface.
/**
This program demonstrates how an icon is adapted to
a component. The component is added to a frame.
*/
public class IconAdapterTester
{
public static void main(String[] args)
{
Icon icon = new MarsIcon(300);
JComponent component = new IconAdapter(icon);
JFrame frame = new JFrame();
frame.add(component, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}

17 18

Encapsulating Context with the


Adapter Pattern: consequences STRATEGY Pattern

• Client and Adaptee work together without any modification to Name: Strategy Design Pattern

Problem Description: Define a family of algorithms, encapsulate each one, and
either.

make them interchangeable. The algorithm is decoupled from the client.



• Adapter works with Adaptee and all of its sub classes
Solution: A Client accesses services provided by a Context. The Context is
configured to use one of the ConcreteStrategy objects (and maintains a reference
• A new Adapter needs to be written for each specialization to it) . The AbstractStrategy class describes the interface that is common to all
(extension) of the Target interface.
the ConcreteStrategies.

Client
• Question: Where does the Adapter Pattern use inheritance? 

Where does it use delegation?

Policy

19 20
Example: switching between network protocols Strategy Pattern example: Network protocols
// Context Object: Network Connection
• Based on location (available network connections), switch between public class NetworkConnection {
different types of network connections
private String destination;
private NetworkInterface intf;
✦LocationManager configures NetworkConnection with a concrete private StringBuffer queue;
NetworkInterface based on the current location
public NetworkConnect(String destination, NetworkInterface intf) {
this.destination = destination; this.intf = intf;
✦Application uses the NetworkConnection independently of concrete this.intf.open(destination);
NetworkInterfaces (NetworkConnection uses delegation).
}
public void send(byte msg[]) {
Application queue.concat(msg);
NetworkConnection NetworkInterface
if (intf.isReady()) {
intf.send(queue);
send() open()
receive() close() queue.setLength(0);
setNetworkInterface() send()
LocationManager receive() }
}
public byte[] receive () {
return intf.receive();
Ethernet WaveLAN UMTS
}
WaveLAN = WiFi open() open() open() public void setNetworkInterface(NetworkInterface newIntf) {
UMTS = 3G mobile close()
send()
close()
send()
close()
send() intf.close()
phone network receive() receive() receive()
newIntf.open(destination);
intf = newIntf;
21 22
} }

Strategy Pattern example: Network protocols Strategy Pattern example: Layout Managers
//Abstract Strategy,
//Implemented by EthernetNetwork, WaveLanNetwork, and UMTSNetwork (not shown) • Graphical user interfaces are made up of components (ie JButton)

interface NetworkInterface {
void open(String destination); • Components are placed in containers (like JFrame)

void close();
byte[] receive();
void send(StringBuffer queue);
• Containers need to arrange the components on the screen

bool isReady();
} • Some interface toolkits use hard-coded pixel x-y coordinates

//LocationManager: decides on which strategy to use


public class LocationManager { • Java Swing uses a Layout manager to control arrangement and
private NetworkConnection networkConn;
resize components automatically

// called by event handler when location has changed


public void doLocation() { • Advantages:

NetworkInterface networkIntf;
if (isEthernetAvailable()) ✦ Can easily switch "look and feel” (MS windows vs Mac)

networkIntf = new EthernetNetwork();


else if (isWaveLANAvailable()) ✦ Can internationalize strings (resize components for different
networkIntf = new WaveLanNetwork();
else if (isUMTSAvailable()) lengths)
networkIntf = new UMTSNetwork();
networkConn.setNetworkInterface(networkIntf);
}
23 24
}
Predefined Layout Managers:
Strategy Pattern example: Layout Managers
JFrame frame = new JFrame();

frame.setLayout(new FlowLayout());

frame.pack();

frame.setVisible(true);

25 26

Decoupling Entities from Views with the


Strategy Pattern: consequences OBSERVER Pattern
• ConcreteStrategies can be substituted transparently from Context.
Name: Observer Design Pattern

Problem Description: Maintain consistency across the states of one Subject and
• Client (or Policy) decides which Strategy is best, given current many Observers.

circumstances
Solution: The Subject maintains
• New algorithms can be added without modifying Context or Client
some state. One or more
Observers use the state
maintained by the Subject.
Observers invoke the attach()
method to register with a Subject.
Each ConcreteObserver defines
an update() method to
synchronize its state with the
Subject. Whenever the state of
the Subject changes, it invokes its
notify method, which iteratively
invokes each Observer.update()
method.
27 28
Observer Pattern: Java support Observer Pattern: Java support
• We could implement the Observer pattern “from scratch” in Java. • The java.util.Observable class is the base Subject class. Any class
But Java provides the Observable/Observer classes as built-in that wants to be observed extends this class.

support for the Observer pattern.

- public synchronized void addObserver(Observer o)



Adds an observer to the set of observers of this object

• The java.util.Observer interface is the Observer interface. It must be - boolean hasChanged() (see below)

implemented by any observer class. It has one method.


- protected void setChanged()

- void update (Observable o, Object arg)
 Indicates this object has changed (hasChanged now returns true)

This method is called whenever the observed object is changed.
 - public void notifyObservers(Object arg)

Observable o is the observed object.
 - public void notifyObservers()



Object arg can be some value sent by the observed object.
IF hasChanged(), THEN notify all of its observers. Each observer
has its update() method called with this Observable object (and an
argument). The argument can be used to indicate which attribute
of this object has changed. (hasChanged now returns false).
29 30

Observer Pattern example: Observer Pattern example:


import java.util.Observable;
import java.util.Observable;
/* A subject to observe! */ import java.util.Observer;
public class ConcreteSubject extends Observable {
private String name; //An observer of name changes.
private float price; public class NameObserver implements Observer {
public ConcreteSubject(String name, float price) { private String name;
this.name = name;
this.price = price; public NameObserver(ConcreteSubject cs) {
System.out.println("ConcreteSubject created: " + name + " at " + price); cs.addObserver(this);
} name = cs.getName();
public String getName() {return name;} System.out.println("NameObserver created: Name is " + name);
public float getPrice() {return price;} }
public void setName(String name) {
this.name = name; public void update(Observable obj, Object arg) {
setChanged(); ConcreteSubject cs = (ConcreteSubject)obj;
notifyObservers();
} if (!name.equals(cs.getName())) {
public void setPrice(float price) { name = cs.getName();
this.price = price; System.out.println("NameObserver: Name changed to " + name);
setChanged(); }
notifyObservers(); }
} }
} 31 32
Observer Pattern example: Observer Pattern example:
import java.util.Observable; //Test program for ConcreteSubject, NameObserver and PriceObserver
import java.util.Observer; public class TestObservers {
public static void main(String args[]) {
//An observer of price changes. // Create the Subject.
public class PriceObserver implements Observer { ConcreteSubject s = new ConcreteSubject("Corn Pops", 1.29f);
private float price; // Create the Observers, who attach themselves to the subject
NameObserver nameObs = new NameObserver(s);
public PriceObserver(ConcreteSubject cs) { PriceObserver priceObs = new PriceObserver(s);
cs.addObserver(this); // Make changes to the Subject.
price = cs.getPrice(); s.setName("Frosted Flakes");
System.out.println("PriceObserver created: Price is " + price); s.setPrice(4.57f);
} s.setPrice(9.22f);
s.setName("Sugar Crispies");
public void update(Observable obj, Object arg) { }
ConcreteSubject cs = (ConcreteSubject)obj; } ConcreteSubject created: Corn Pops at 1.29
if (cs.getPrice()!= price) { NameObserver created: Name is Corn Pops
price = cs.getPrice(); PriceObserver created: Price is 1.29
System.out.println("PriceObserver: Price changed to " + price); NameObserver: Name changed to Frosted Flakes
} PriceObserver: Price changed to 4.57
} PriceObserver: Price changed to 9.22
} NameObserver: Name changed to Sugar Crispies

33 34

Example: Making Buttons Work with UI Actions. Example: Making Buttons Work with UI Actions.
• Recall the JFrame window we made earlier:
• ActionListeners attach themselves to a button, and when the button
is clicked the code of the actionPerformed method is executed.

• To define the action of the helloButton, we use an anonymous class


to implement the ActionListener interface type:

• These buttons do nothing if you click on them.


final JTextField textField = new JTextField(FIELD_WIDTH);
JButton helloButton = new JButton("Say Hello”);
• We need to add listener objects to the button.

helloButton.addActionListener(new
• Listener objects implement the following Interface:
ActionListener() {
public void actionPerformed(ActionEvent event) {
textField.setText("Hello, World!");
public interface ActionListener {

}
int actionPerformed(ActionEvent event);

});
}

• When the button is clicked, the textField will be set.

• The ActionEvent parameter contains information about the event,


such as the event source. But we usually don’t need that info. • Note: the anonymous class can access fields from enclosing class
(like textField) IF they are marked Final.
35 36
Example: Making Buttons Work with UI Actions. Example: Making Buttons Work with UI Actions.
public class ActionTester {
public static void main(String[] args) { • How is this an example of the OBSERVER pattern?

JFrame frame = new JFrame();


final JTextField textField = new JTextField(20);
textField.setText("Click a button!");
JButton helloButton = new JButton("Say Hello");
helloButton.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent event) {
textField.setText("Hello, World!");
}
});
JButton goodbyeButton = new JButton("Say Goodbye");
goodbyeButton.addActionListener(new
ActionListener() {
public void actionPerformed(ActionEvent event) {
textField.setText("Goodbye, World!");
}
});
frame.setLayout(new FlowLayout());
frame.add(helloButton); frame.add(goodbyeButton); frame.add(textField); • Note:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); ✦Does not use the Java Observer/Observable classes.

frame.setVisible(true);
} ✦The JButton has no state that the observer cares about.
}
37 38

Encapsulating Hierarchies with the 



Observer Pattern: consequences COMPOSITE Pattern
• Decouples a Subject from the Observers. Subject knows only that Name: Composite Design Pattern

it contains a list of Observers, each with an update() method. 
 Problem Description: Represent a hierarchy of variable width and depth so that
(The subject and observers can belong to different layers.)
leaves and composites can be treated uniformly through a common interface.

Solution: The Component interface specifies the services that are shared among
• Observers can change or be added without changing Subject.
Leaf and Composite (operation()). A Composite has an aggregation association
with Components and implements each service by iterating over each contained
• Observers can ignore notifications (decision is not made by Component. The Leaf services do most of the actual work.
Subject).

• Can result in many spurious broadcasts (and calls to getState())


when the state of a Subject changes.

39 40
Example: A hierarchy of user interface objects Example: A hierarchy of user interface objects
• Anatomy of a preference dialog. Aggregates, called Panels, are • An object diagram (it contains instances, not classes) of the
used for grouping user interface objects that need to be resized and previous example:

moved together.

prefs:Window

Top panel
top:Panel main:Panel buttons:Panel

Main panel title:Label c1:Checkbox ok:Button

c2:Checkbox cancel:Button

c3:Checkbox
Button panel
c4:Checkbox

41 42

Example: A hierarchy of user interface objects Composite Pattern example: File system
• A class diagram, for user interface widgets

* //Component Node, common interface


Component
interface AbstractFile {
move() public void ls();
resize() }

// File implements the common interface, a Leaf


class File implements AbstractFile {
Label Button Checkbox Composite private String m_name;
move() public File(String name) {
resize()
m_name = name;
}
public void ls() {
Window
System.out.println(CompositeDemo.g_indent + m_name);
Panel
}
}
Applet

43 44
Composite Pattern example: File system Composite Pattern example: File system
public class CompositeDemo {
// Directory implements the common interface, a composite
public static StringBuffer g_indent = new StringBuffer();
class Directory implements AbstractFile {
private String m_name;
public static void main(String[] args) {
private ArrayList<AbstractFile> m_files = new ArrayList<AbstractFile>();
Directory one = new Directory("dir111"),
public Directory(String name) {
two = new Directory("dir222"),
m_name = name;
thr = new Directory("dir333");
}
File a = new File("a"), b = new File("b"),
public void add(AbstractFile obj) {
c = new File("c"), d = new File("d"), e = new File("e");
m_files.add(obj);
one.add(a);
}
one.add(two);
public void ls() {
one.add(b);
System.out.println(CompositeDemo.g_indent + m_name);
two.add(c); Output: dir111
CompositeDemo.g_indent.append(“ “); // add 3 spaces a
two.add(d);
for (int i = 0; i < m_files.size(); ++i) { dir222
two.add(thr);
AbstractFile obj = m_files.get(i);
thr.add(e); c
obj.ls();
one.ls(); d
}
}
//remove the 3 spaces:
}
dir333
CompositeDemo.g_indent.setLength(CompositeDemo.g_indent.length() - 3); e
}
b
}

45 46

Adding Behavior Dynamically with the 



Composite Pattern: consequences DECORATOR Pattern
• Client uses the same code for dealing with Leaves or Composites
Name: Decorator Design Pattern

Problem Description: Attach additional responsibilities to an object dynamically.
• Leaf-specific behavior can be modified without changing the Decorators provide a flexible alternative to subclassing for extending functionality.

hierarchy
Solution: The Component interface specifies the services for objects that can
have responsibilities added to them. A ConcreteComponent is an independent
• New classes of leaves (and composites) can be added without object to which additional responsibilities can be attached. The Decorator
changing the hierarchy
conforms to the Component interface, and maintains a reference to a Component
to which it adds responsibilities.

• Could make your design too general. Sometimes you want


composites to have only certain components. May have to add
your own run-time checks.

47 48
Example: Adding scrollbars to a UI Component Decorator Pattern: Scroll Bars
• When a component contains more information than can be shown
• The JScrollPane is an instance of the DECORATOR Pattern.

on the screen, it becomes necessary to add scroll bars.

• This is not a hierarchy, the JScrollPane contains only 1 Component.

• This code adds scroll bars to a text area (a text area is a box where
you can enter multiple lines of text):
• The JScrollPane is itself a Component.

JTextArea area = new JTextArea(20, 40); // 20 rows, 40 columns ✦It has the same methods as JTextArea, implemented by calling the method
JScrollPane scroller = new JScrollPane(area);
on JTextArea and modifying the result.

frame.add(scroller, BorderLayout.CENTER);
✦It can be decorated by another JScrollPane
JScrollPane(Component view)
Creates a JScrollPane that displays the contents of the specified component, where both
horizontal and vertical scrollbars appear whenever the component's contents are larger
than the view.

49 50

Encapsulating Subsystems with the


Decorator Pattern: consequences FACADE Pattern
• Component objects can be decorated (visually or behaviorally Name: Facade Design Pattern

enhanced)
Problem Description: Reduce coupling between a set of related classes and the
rest of the system. Provide a simple interface to a complex subsystem.

• The decorated object can be used in the same way as the Solution: A single
undecorated object
Facade class
implements a high-level
• The component class does not want to take on the responsibility of interface for a
the decoration (loose coupling!)
subsystem by invoking
the methods of lower-
• There may be an open-ended set of different kinds of decorations.

level classes. A Facade


• A decorated object can itself be decorated. And so on. And so on.
is opaque in the sense
that a caller does not
access the lower-level
classes directly. The use
of Facade patterns
recursively yields a
layered system.
51 52
Example: Compiler subsystem Facade Pattern: consequences
• Compiler class is a facade hiding the Scanner, Parser, • Shields a client from the low-level classes of a subsystem.

ProgramNodeBuilder and CodeGenerator.


Some specialized apps might
need to access the classes • Simplifies the use of a subsystem by providing higher-level
directly, but most don’t. methods.

• Promotes “looser” coupling between subsystems.

• Note the use of delegation to reduce coupling.

• Note the similarity to the Controller GRASP pattern.

53 54

Heuristics for Selecting Design Patterns


• Use key phrases from design goals to help choose pattern

Phrase Design Pattern

“Must support aggregate structures”

Composite
“Must allow for hierarchies of variable depth and width”

“Must have mechanism to process aggregate structure”

Iterator
“Must support multiple traversals at same time”
“Must comply with existing interface”

Adapter
“Must reuse existing legacy component”
“Must be notified of changes” Observer
“Must allow functionality to be added during runtime”

Decorator
“Client programs must be able to add functionality”
“Policy and mechanisms should be decoupled”

“Must allow different algorithms to be interchanged at Strategy


runtime” 55

You might also like