Object Oriented Programming Lecture 7: Algorithm animation using strategy and factory patterns, The...
-
Upload
alvin-mclaughlin -
Category
Documents
-
view
221 -
download
3
Transcript of Object Oriented Programming Lecture 7: Algorithm animation using strategy and factory patterns, The...
Object Oriented Programming
Lecture 7:Algorithm animation using strategy and factory patterns, The Adapter design pattern
www.hh.se/staff/jebe/oop2006/main.html
Last lecture Unit testing
Structured testing on units (classes)
Reduce complexity by incremental testing on small components
No clutter in the source code Demonstration of the JUnit
tool Module in Netbeans Exercise 10: using JUnit
Testing inSoftware development
Requirements analysis
Design
Implementationand unit testing
Integration andsystem testing
Maintenance
In this OOP Course
In the Software engineering course
Template Pattern Purpose: A generic Class for objects
which: Shares functionality (i.e. same concrete methods
in Java) But also has some method implementations that
need to be different (abstract) The common methods are encapsulated in
the template class We used Template pattern in
the Doublebuffered Animation Applet the Function Plotter
Structure of the Template patternAbstract Class
Concrete implementations (invariant parts)
Abstract methods
Subclass extending the template (Concrete class)
Implements the hookMethods
Generic Class
templateMethod()
hookMethod1()
hookMethod2()
Concrete Class
hookMethod1()
hookMethod2()
Strategy pattern Purpose: An abstraction to decouple
algorithms from its host Force provision of a set of required services
(methods) but with different implementations With strategy pattern we can implement
contractually compatible classes with different algorithms
A useful methodolgy to dynamically swap algorithms in a program
Design Pattern: Strategy
The plotter The abstract strategy
Concrete implementations
Context
ContextMethod()
Strategy
algorithm()
ConcreteStrategyA()
algorithm() algorithm()
ConcreteStrategyB()
Animation of Sorting Algorithms Applet to visualize
execution of sorting algorithms
It should be easy to adapt for different sort
algorithms different displays
Demonstrates usage of Factory, Strategy and Observer - Observable patterns
Sorting Algorithms Input to the Algorithm Sorter: an array of
Integers Choosing different sorting algorithms
executing with different complexities Bubble Sort O(n2) Quick Sort O(n*log n) Insertion Sort O(n2) ...
The framework should adapt to different algorithms and different display strategies
Generic Algorithm Animation – Design Issues
Algorithm Abstraction? Problem: How can we easily change between
different algorithms? Integration with Animation during sorting?
Problem: The screen should be redrawn after each iterative step, running the algorithm
Display Abstractions? Problem: We will also need a modular way to
hook different graphical displays
Starting the design of the Algorithm Animator
Two design pattern candidates: Template – Not flexible
since we want to assign any sorting algorithm after compile time (recall the function multiplotter from last lecture)
Strategy – More flexible since we can decouple the sort algorithms from the animator
We will use strategy pattern to separate the algorithm from animator
Design Pattern: Strategy
The Strategy interface
Concrete Sort algorithms
So we can render between each sort iteration!
Algorithm Animator
Sortalgorithm()
Strategy
sort()
BubbleSort
sort() sort()
QuickSort
The Sorting Abstraction Has an abstract sort method
Called by the Animator to start sorting Issue: How do we render the animation between each
swap during the sort? Solution: We implement a pause() function!
Will pause the sorting and render after each swap during the sorting process
Since all sorting algorithms involve swapping of two values Makes sense to factor swap into the sorting
abstraction Issue: How do we render the image after each swap?
Use a Animator reference to call: animator.pause(); We will use the Observer-Observable pattern!
The sorting abstraction
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;
}}
A concrete sorting algorithm
class BubbleSortAlgorithm extends SortAlgorithm { 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(); } }}
The algorithm animator The AlgorithmAnimator template
abstract method for initAnimator(); A an applet
Implements Runnable and Observer A thread controls frame delay
Performs animation of an abstract SortAlgorithm
The animation is controlled by Thread to handle frame delay The Observer Observable pattern for drawing
synchronisation
A Bubble sorter using the AlgorithmAnimator template
public class BubbleSorter
extends AlgorithmAnimator
{
protected void initAnimator(){
theAlgorithm = new BubbleSortAlgorithm();
}
}
How can we improve the design?
The different sort algorithms are strongly coupled to the specific Animator
We want the sorting algorithms be easily interchangable Loading algorithms at startup
We want the client (Algorithm Animator) be unaware of the concrete algorithms
Improving our design using the Factory Design Pattern
We can separate 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) Can be abstractly ”hooked” to the
animator The concrete algorithms will be
coupled to the Algorithm Factory instead of the Algorithm Animator
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()
StaticAlgoFactory Input: the name of a sorting algorithm
(String) Output: A concrete instance of the
abstract SortAlgorithm (a product) The Contractual Interface:
abstract makeSortAlgorithm(String algName){...}
Must be defined by every concrete AlgoFactory Binds the actual algorithm to the animator
The Strategy abstraction of Factory and a concrete implementation
public interface SortAlgorithmFactory{
SortAlgorithm makeSortAlgorithm(String name);
}
Algorithm Animator
Sortalgorithm()
SortingAlgorithm
sort()
BubbleSort
sort() sort()
QuickSort
Algorithm Factory
makeSortAlgorithm()
StaticAlgoFactory
makeSortAlgorithm()
A concrete Algorithm Factory
public class StaticAlgoFactoryimplements SortAlgorithmFactory {
public SortAlgorithmmakeSortAlgorithm(String name) {
if ("BubbleSort".equals(name)) return new BubbleSortAlgorithm(); else if ("QuickSort".equals(name)) return new QuickSortAlgorithm(); else return new BubbleSortAlgorithm(); }}
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); }}
Invoking the AlgorithmAnimation applet
<applet code=Sort.class width=100 height=100>
<param name = alg value = QuickSort>
</applet>
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!
New Design Pattern: Adapter
A design pattern that can be used to: reuse classes without modifying the
code, instead we convert the interface! narrow interfaces when just needing a
small subset of the methods
Simple example: Narrowing of thye MouseListener with MouseAdapter
Some classes have an implementation which does not ”fit” the requirements
Or we might only need few of the availabe methods Ex. listening for mouse actions
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 have to
override the methods we need in the mouse listener interface
The MouseListener interfacevoid 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.
The MouseAdaptervoid 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.
A Simple MouseClick listenerPublic MouseClick extends MouseAdapter{
void mouseClicked(MouseEvent e){
System.out.println(”Disco!”);
}
/**
* Other MouseListener methods can be omitted
**/
}
Structure of the Adapter pattern – Class Adapter
Client Target
doStuff()
Adapter
doStuff()
Adaptee
doSomeTask()
doStuff(){….doSomeTask();…return result;
}
Structure of the Adapter pattern – Object Adapter
Client Target
doStuff()
Adapter
doStuff()
Adaptee
doSomeTask()
adaptee.doSomeTask();