You are on page 1of 6

Design by Abstraction What is a Pattern?

• Patterns represent generic solutions to recurring problems


• Design patterns
• How does software design resemble architectural design?
– What is a design pattern?
– Patterns covered in this chapter: Singleton, Template
Method, Strategy, Iterator, Factory
• Designing generic components
– Factorization
– Generalization • Classification of commonly occurring design patterns
– Abstract Coupling • These categories are based on the classic textbook in
• Example programs the field by Gamma, et. al.
– Generic animation applet
– Generic function plotter
– Animation of sorting algorithms

The Singleton Pattern - 1 The Singleton Pattern - 2


• This is perhaps the easiest design patter
• The goal is to insure that only one instance of an
object is possible

• Implementing singletons in Java


– Make the method getInstance public and static
• Give some applications where you think the – getInstance calls the constructor for the singleton
singleton design pattern would be useful? pattern, which is not public, it is protected
– In this way, only one instance can be created

The Spooler as a Singleton The Exception and the Spooler


public class SingletonException extends RuntimeException {
public class singleSpooler //new exception type for singleton classes
{ public SingletonException() {
super();
static public void main(String argv[])
}
{
public SingletonException(String s) {
Spooler pr1, pr2; super(s);
//open one printer--this should always work }
System.out.println("Opening one spooler"); }
try{ pr1 = new Spooler(); public class Spooler {
} //this is a prototype for a printer-spooler class
catch (SingletonException e) //such that only one instance can ever exist
static boolean instance_flag = false; //true if one instance
{System.out.println(e.getMessage());}
public Spooler() throws SingletonException
//try to open another printer --should fail
{
System.out.println("Opening two spoolers"); if (instance_flag)
try{ pr2 = new Spooler(); throw new SingletonException("Only one printer allowed");
} else
catch (SingletonException e) instance_flag=true; //set flag for one instance
{System.out.println(e.getMessage());} System.out.println("printer opened");
} }
}
}

1
A Question Factorization
• What is factorization?
• What will be printed when the main method in
singleSpooler is executed?

• Why would factorization reduce risk?


• What is the most common form of factorization?

Press here to see if your answer is correct

Factorization by Inheritance - 1 Factorization by Inheritance - 2


• Before • When would inheritance be preferred to a function?

• When would a function be preferred to inheritance?

• After factorization by Inheritance


• Describe a practical situation where you would use
factorization by inheritance?

Factorization by Delegation - 1 Factorization by Delegation - 2


• The common code is put • Which method is more general, inheritance or
into a separate class delegation?

• Describe a practical situation where you would use


• Invoking the common method factorization by delegation?

2
import java.awt.*;
An Animation Applet public class AnimationApplet extends java.applet.Applet
implements java.lang.Runnable {

• All animations have a set of common operations public void start() {


animationThread = new Thread(this);
animationThread.start(); }
public void stop() {
animationThread = null; }
public void run() {
while (Thread.currentThread() == animationThread) {
try {
Thread.currentThread().sleep(delay);
} catch (InterruptedException e) {}
• Using the animation repaint();
applet to implement } }
final public void setDelay(int delay) {
yet another version this.delay = delay;
of our digital clock }
final public int getDelay() { Implementation of the
return delay;
} Animation Applet
protected Thread animationThread;
protected int delay = 100;
}

Use of the Animation Applet Designing for Flexibility


import java.awt.*;
import java.util.Calendar;

public class DigitalClock3 extends AnimationApplet {


public DigitalClock3() {
setDelay(1000);
} Start Ticking
public void paint(Graphics g) { • How does the animation applet demonstrate
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
flexibility?
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
g.setFont(font);
g.setColor(color); • Where is it weak in flexibility?
g.drawString(hour + ":" + minute / 10 + minute % 10 +
":" + second / 10 + second % 10, 10, 60);
}
protected Font font = new Font("Monospaced", Font.BOLD, 48); • How can it be improved?
protected Color color = Color.green;
}

Adding Double Buffering Avoiding Problems


• Goals • This does not allow additional initialization; the super init
needs to be called

• A Simplistic Approach

• Not invoking super.init( ) will cause a null pointer


exception at runtime; this is not caught by the compiler
• Such errors are a problem of design, the goal should be:

3
import java.awt.*; protected void initAnimator() {}
A Better
public abstract class DBAnimationApplet
extends AnimationApplet { Version - 1 abstract protected void paintFrame(Graphics g);

final public void update(Graphics g) {


if (doubleBuffered) { protected DBAnimationApplet(boolean
doubleBuffered) {
paintFrame(offscreen);
g.drawImage(im, 0, 0, this); this.doubleBuffered = doubleBuffered;
} else { }

}
// super.update();
protected DBAnimationApplet() {
A Better
}
final public void paint(Graphics g) {
this.doubleBuffered = true; Version - 2
}
paintFrame(g);
} protected boolean doubleBuffered;
final public void init() {
protected Dimension d;
d = getSize();
protected Image im;
im = createImage(d.width, d.height);
protected Graphics offscreen;
offscreen = im.getGraphics();
initAnimator();
} }

DBAnimation Applet import java.awt.*;

public class BouncingBall2 extends DBAnimationApplet {

public BouncingBall2() {
super(true); // double buffering
}

protected void initAnimator() { Using Double


String att = getParameter("delay");
if (att != null) Buffering - 1
setDelay(Integer.parseInt(att));
x = d.width * 2 / 3 ;
• Why does digital clock not use double buffering }
y = d.height - radius;

while the bouncing ball will use it?


protected void paintFrame(Graphics g) {
g.setColor(Color.white);
g.fillRect(0,0,d.width,d.height);
if (x < radius || x > d.width - radius) {
dx = -dx;
}

Using Double Buffering - 2 The Template Design Pattern - 1


if (y < radius || y > d.height - radius) {
dy = -dy;
}
x += dx; y += dy;
g.setColor(color);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}

protected int x, y;
protected int dx = -2, dy = -4;
protected int radius = 20;
protected Color color = Color.green;
}

Bounce that Ball

4
The Template Design Pattern - 2 Drawing Triangles
• Motivation
– Where a user is drawing on a sketch pad they may
want to draw a triangle; in some cases the user may
want the triangle to be isosceles or a right triangle
– It is often difficult for the user to be sure the triangle
meets the desired criteria from the visual image
– This drawing routine may adjust the “third point” to
• Can you think of any other applications that could make sure the triangle meets any special criteria
benefit from the Template design pattern?
p3 Adjusted p3
third line
second line
p1 p2
first line

The Abstract
import java.awt.*;
public abstract class Triangle { The Standard Triangle
private Point p1, p2, p3; Triangle
public Triangle(Point a, Point b, Point c) {
p1 = a; p2 = b; p3 = c; Class No adjustments are made to the second line to
} force it to be a “special” type of triangle
public void draw(Graphics g) {
//This routine draws a general triangle
drawLine(g, p1, p2); import java.awt.*;
Point current = draw2ndLine(g, p2, p3); public class stdTriangle extends Triangle {
closeTriangle(g, current);
public stdTriangle(Point a, Point b, Point c) {
}
//--------------------------------------- super(a, b, c);
public void drawLine(Graphics g, Point a, Point b) { }
g.drawLine(a.x, a.y, b.x, b.y); public Point draw2ndLine(Graphics g, Point a, Point b) {
}
g.drawLine(a.x, a.y, b.x, b.y);
//---------------------------------------
abstract public Point draw2ndLine(Graphics g, Point a, Point b); return b;
//--------------------------------------- }
public void closeTriangle(Graphics g, Point c) { }
//draw back to first point
g.drawLine(c.x, c.y, p1.x, p1.y);
}
}

import java.awt.*; double slope = dy2 / dx2;


import
import
java.awt.event.*;
java.util.*;
The Isosceles double intercept = c.y - slope* c.x;
//move point c so that this is an isoceles triangle
import
import
javax.swing.text.*;
javax.swing.*;
Triangle - 1 newcx = c.x; newcy = c.y;
while (Math.abs(side1 - side2) > 1) {
import javax.swing.event.*; newcx += incr; //iterate a pixel at a time until close
newcy = (int)(slope* newcx + intercept);
public class IsocelesTriangle extends Triangle { dx2 = newcx - b.x;
private Point newc; dy2 = newcy - b.y;
private int newcx, newcy; side2 = calcSide(dx2, dy2);
private int incr; } The Isosceles
knew = new Point(newcx, newcy);
public IsocelesTriangle(Point a, Point b, Point c) { } Triangle - 2
super(a, b, c); //calculate length of side
double dx1 = b.x - a.x; private double calcSide(double dx, double dy) {
double dy1 = b.y - a.y; return Math.sqrt(dx*dx + dy*dy);
double dx2 = c.x - b.x; }
double dy2 = c.y - b.y; //draws 2nd line using saved new point
double side1 = calcSide(dx1, dy1); public Point draw2ndLine(Graphics g, Point b, Point c) {
double side2 = calcSide(dx2, dy2); g.drawLine(b.x, b.y, newc.x, newc.y);
if (side2 < side1) return newc;
incr = -1; }
else }
incr = 1;

5
A Right Triangle Why Triangle is a Template pattern
• Using the isosceles triangle as a guide, write the • The generic class is Triangle
right triangle class • The concrete classes are stdTriangle, isoscelesTriangle,
and rightTriangle
• Assume the right angle is between the second and • The template methods are drawLine and closeTriangle
third legs, so the first leg is the hypotenuse • The hook method is draw2ndLine

You might also like