1 Object Oriented Programming Lecture XII The Adapter,Template, Strategy and Factory design patterns

Preview:

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

Recommended