Upload
jalyn-render
View
224
Download
0
Embed Size (px)
Citation preview
1
Object Oriented ProgrammingLecture XII
The Adapter,Template, Strategy and Factory design patterns
2
Last Lecture
• More design by abstraction– Design patterns
• the Strategy pattern (again)– Making use of interfaces
• the Factory pattern– making use of abstract classes and inheritance
• the Adapter design pattern
– A concrete case study• An algorithm animator• Applying the Template, Strategy, Observer-Observable and the
Factory patterns
3
Today’s Talk
• Concurrency by multithreading– Design patterns
• the Strategy pattern (again)– Making use of interfaces
• the Factory pattern– making use of abstract classes and inheritance
• the Adapter design pattern
– A concrete case study• An algorithm animator• Applying the Template, Strategy, Observer-Observable and
the Factory patterns
4
Template Pattern
• Purpose: To implement a generic, reusable Class which:– encapsulates shared and necessary functionality
• i.e. concrete methods in Java– but also allowing specific methods to be user
specified (abstract in the template)• the abstract keyword enforce user definition of these
methods
• We have used the Template pattern in – the generic Doublebuffered Animation Applet– the generic Function Plotter
5
Structure of the Template pattern
Abstract Class
Concrete implementations (invariant parts)
Abstract hook methods
Subclass extending the template (Concrete class)
Definition of the methods
Generic Class
templateMethod()
hookMethod1()
hookMethod2()
Concrete Class
hookMethod1()
hookMethod2()
6
Strategy pattern
• Purpose: An abstraction for decoupling of algorithms from its context– to enforce provision of a set of required services
(methods) but using different algorithms• The abstract strategy specifies the contractual
interface• A concrete strategy must implement the
contractual interface, and provide the definition of a specific strategy
• A very useful method for dynamic coupling of different algorithms in a program
7
Design Pattern: Strategy
The plotter The abstract strategy:
An Interface or Abstract Class
Concrete implementations
Context
ContextMethod()
Strategy
algorithm()
ConcreteStrategyA()
algorithm() algorithm()
ConcreteStrategyB()
8
Animation of Sorting Algorithms
• Applet to visualize the execution of sorting algorithms
• Should be easy to adapt – for different sort algorithms– for different displays
• Demonstrates usage of– the Factory pattern,– the Strategy pattern– and the Observer -
Observable pattern
9
A Framework for Sorting Algorithms
• Input to the Algorithm Sorter: – an array of integers (int[] arr)
• Ability to choose different sorting algorithms of different complexity– Bubble Sort complexity Ο(n2)– Quick Sort complexity O(n*log n)– Insertion Sort complexity O(n2)– ...
• The framework should also be adaptable to different display strategies– how we visualize the elements to be sorted
10
Generic Algorithm Animation: Design Issues
• Algorithm abstraction?– Problem: How can we easily change between
different algorithms?
• Integration with animator?– Problem: The screen should be redrawn after each
iterative step, when running the algorithm
• Display abstractions?– Problem: We also need a methodolgy to be able
exchange different graphical displays
11
First design of the Algorithm Animator
• Two design pattern candidates:– Template: Not flexible
enough since we want to dynamically assign any sorting algorithm (recall the function multiplotter from last lecture)
– Strategy: More flexible since we can decouple the sorting algorithms from the animator
• We will use the Strategy pattern to separate algorithms from animator
12
Design Pattern: Strategy
Abstract strategy for sort algorithms
Concrete Sort algorithms
So we can render an image between each step in the sort process
Algorithm Animator
Sortalgorithm()
Strategy
sort()
BubbleSort
sort() sort()
QuickSort
13
The Sorting Abstraction
• An abstract sort method (hook method)– called by the animator to start sorting
• How do we render each element swap during the sort?– We implement a pause() function!
• Pause the sorting and render the image after each swap during the sort process
• All sorting algorithms do swapping of two elements• Makes sense to put the swap in the sorting abstraction
• How do we order animator to render the image after each swap?– use a reference to Animator so we can call by
animator.pause();– or…we can use the Observer-Observable pattern!
14
The sorting abstraction –applying template pattern
public abstract class SortAlgorithm extends java.util.Observable {
abstract void sort(int a[]); protected void pause(){
setChanged();notifyObservers();
} protected static void swap(int a[], int i, int j) {
int T;T = a[i]; a[i] = a[j]; a[j] = T;
}}
15
A concrete sorting algorithm
class BubbleSortAlgorithm extends SortAlgorithm { public void sort(int a[]) { for (int i = a.length; --i >= 0; ) for (int j = 0; j < i; j++) { if (a[j] > a[j+1]) swap(a, j, j+1); pause(); } }}
16
The algorithm animator
• The AlgorithmAnimator template– abstract method for initAnimator();
• A an applet– implements Runnable and Observer
• Performs animation of an abstract SortAlgorithm
• The animation is controlled by– a thread to handle frame delay– the Observer Observable pattern for abstract object
interaction
17
The AlgorithmAnimatorpublic abstract class AlgorithmAnimator extends JApplet implements Runnable,Observer{ … protected SortAlgorithm theAlgorithm; protected int [] arr; … public void start(){
if(animationThread == null){ animationThread = new Thread(this); finished = false; animationThread.start();}
} public void stop(){
finished = true; } ….
18
The AlgorithmAnimator … public void run(){
theAlgorithm.sort(arr); } final public void update(Observable obs, Object o) {
if (!finished) { try{
Thread.currentThread().sleep(delay); }catch(InterruptedException e) {} repaint();}
} public void setDelay(int d){
delay = d; }…
19
The AlgorithmAnimator … public final void init() {
setDelay(20); scramble();initAnimator();theAlgorithm.addObserver(this);
} protected abstract void initAnimator(); protected void scramble() {
arr = new int[getSize().height / 2];for(int i = arr.length; --i >= 0;) arr[i] = i;for(int i = arr.length; --i >= 0;) { int j = (int)(i * Math.random()); SortAlgorithm.swap(arr, i, j); }
}…}
20
A Bubble sorter using the AlgorithmAnimator
public class BubbleSorter
extends AlgorithmAnimator
{
protected void initAnimator(){
theAlgorithm = new BubbleSortAlgorithm();
}
}
21
How can we improve the design?
• The different sort algorithms are strongly coupled to the specific Animator
• We want the sorting algorithms to easily be interchangable– deciding what algorithms at startup time
• We want the client (algorithm animator) to be ”unaware” of the concrete algorithms
22
Improving our design using the Factory Design Pattern
• We can put the creation of algorithms in a separate class
• We call this class a Factory and it produces products (Sort Algorithms) of a certain type (Sorting Abstraction)
• The concrete algorithms will be coupled to the Algorithm Factory
23
The Factory Design Pattern
Using Strategy to decouple the algorithms
The concrete Factory
Algorithm Animator
Sortalgorithm()
SortingAlgorithm
sort()
BubbleSort
sort() sort()
QuickSort
Algorithm Factory
makeSortAlgorithm()
StaticAlgoFactory
makeSortAlgorithm()
24
The StaticAlgoFactory class
• Input: the name of a sorting algorithm (String)• Output: A concrete instance of the abstract
SortAlgorithm (a product)• The contractual interface for AlgoFactories:
– abstract SortAlgorithm makeSortAlgorithm(String algName){...}
– must be defined by every concrete AlgoFactory– binds the actual algorithm to the animator
25
The Factory
public interface SortAlgorithmFactory{
SortAlgorithm makeSortAlgorithm(String name); }
Algorithm Animator
Sortalgorithm()
SortingAlgorithm
sort()
BubbleSort
sort() sort()
QuickSort
Algorithm Factory
makeSortAlgorithm()
StaticAlgoFactory
makeSortAlgorithm()
26
A concrete Algorithm Factory
public class StaticAlgoFactoryimplements SortAlgorithmFactory {
public SortAlgorithm makeSortAlgorithm(String name) { if("BubbleSort".equals(name)) return new BubbleSortAlgorithm(); else if ("QuickSort".equals(name)) return new QuickSortAlgorithm(); else return new BubbleSortAlgorithm(); }}
27
Using the improved AlgorithmAnimator
import java.awt.*;
public class Sort extends AlgorithmAnimator{protected void initAnimator(){
String algoName = getParameter("alg");SortAlgorithmFactory factory = new
StaticAlgoFactory();theAlgorithm =
factory.makeSortAlgorithm(algoName); }}
28
Invoking the AlgorithmAnimation applet
<applet code=Sort.class width=100 height=100>
<param name = alg value = QuickSort>
</applet>
29
Further improvement: Decoupling the SortDisplay• public int getArraySize()
– method to provide the arraysize so we know the maximum bars we can draw and animate using this display
• public void display(int[] a, Graphics g, Dimension d)– the abstract drawing method, to be called by paint
• To be implemented as exercise!
30
New Design Pattern: Adapter
• A design pattern that can be used to:– reuse classes which can not be used directly without
some modification– narrow interfaces when just needing a small subset
of the methods
31
Narrowing with an adapter
• Some classes have an implementation which do not ”fit” perfectly with the requirements
• ...or we might only need few of the availabe methods, from a class requiring a certain contractual interface to be defined– eg. when listening for mouse actions
32
The MouseAdapter
• MouseAdapter is a class implementing the MouseListener interface– The adapter defines all MouseListener
methods empty (No action as default)– By extending the MouseAdapter, we only
need to override the methods we need from the mouse listener interface
33
The MouseListener interface
void mouseClicked(MouseEvent e); Invoked when the mouse button has been clicked (pressed and released) on a component.
void mouseEntered(MouseEvent e); Invoked when the mouse enters a component.
void mouseExited(MouseEvent e); Invoked when the mouse exits a component.
void mousePressed(MouseEvent e); Invoked when a mouse button has been pressed on a component. void mouseReleased(MouseEvent e);
Invoked when a mouse button has been released on a component.
34
The MouseAdapter implements MouseListenervoid mouseClicked(MouseEvent e){/* no action */}
Invoked when the mouse has been clicked on a component.
void mouseEntered(MouseEvent e) {/* no action */}Invoked when the mouse enters a component.
void mouseExited(MouseEvent e) {/* no action */}Invoked when the mouse exits a component.
void mousePressed(MouseEvent e) {/* no action */}Invoked when a mouse button has been pressed on a component.
void mouseReleased(MouseEvent e) {/* no action */}
Invoked when a mouse button has been released on a component.
35
A Simple MouseClick listener
public MouseClick extends MouseAdapter{
void mouseClicked(MouseEvent e){
System.out.println(”Disco!”);
}
/**
* Other MouseListener methods can be omitted
**/
}
36
Structure of the Adapter pattern: Class Adapter
Client Target
doStuff()
Adapter
doStuff()
Adaptee
doSomeTask()
doStuff(){….doSomeTask();…return result;
}
37
Structure of the Adapter pattern: Object Adapter
Client Target
doStuff()
Adapter
doStuff()
Adaptee
doSomeTask()
adaptee.doSomeTask();