Back to Design Patterns
Study Group page
An Example of the Factory Method (p 107)
Intent
Define an interface for creating an object, but let subclasses decide which
class to instantiate. Factory Method lets a class defer instantiation to
subclasses.
An example from Sun's Java Development Kit (JDK beta)
The general purpose abstract class, Component, provides a good
deal of functionality including the ability to repaint a
component (an Applet is a component), set or get Font styles, post or handle
events, show or hide the component, etc. The Component
class defines a Factory Method called createImage
which creates new objects of the class Image. Applets (like the example
below) often use this method to implement double-buffering.
Source code - Using the Component's createImage factory method
import java.awt.Graphics;
import java.awt.*;
public class Animator2 extends java.applet.Applet implements Runnable
{
final int MAX_IMAGES = 9;
Thread animThread = null;
Image frame[] = new Image[MAX_IMAGES];
Image offScrImg;
Graphics offScrGraphics;
boolean imagesLoaded = false;
final int PauseSeconds = 380;
int frame_number;
public String getAppletInfo()
{ return "Animator2 by Joshua Kerievsky"; }
public void init()
{
try
{
//////////// call to Factory Method //////////////
///////////////// createImage ///////////////////
offScrImg = createImage(size().width, size().height);
offScrGraphics = offScrImg.getGraphics();
} catch (Exception e)
offScrGraphics = null;
}
public void start()
{
if (animThread == null)
{
animThread = new Thread(this);
animThread.start();
}
}
public void stop()
{
if (animThread != null && animThread.isAlive())
animThread.stop();
animThread = null;
}
void pause(int time)
{
try { Thread.sleep(time); }
catch (InterruptedException e) {}
}
private void loadImages()
{
getAppletContext().showStatus("Loading up animation images...");
// load up all images (but last) using a MediaTracker
MediaTracker trk = new MediaTracker(this);
for (int i=0; i < MAX_IMAGES-1; i++)
{
frame[i] = getImage(getCodeBase(), i+".gif");
trk.addImage(frame[i], i+1);
try { trk.waitForID(i+1); } // wait for complete image to be loaded
catch (Exception e)
frame[i] = null;
}
imagesLoaded = true;
getAppletContext().showStatus("All images loaded.");
}
public void run()
{
frame_number = MAX_IMAGES - 1; // start with last
while (true)
{
if ( !imagesLoaded )
loadImages();
repaint();
pause(PauseSeconds);
frame_number++;
if (frame_number == MAX_IMAGES) frame_number = 0;
}
}
public void update(Graphics g)
{ paint(g); }
public void paint(Graphics g)
{
if (offScrGraphics != null)
{
offScrGraphics.drawImage(frame[frame_number], 0, 0, this);
g.drawImage(offScrImg,0,0,this);
}
else
g.drawImage(frame[frame_number],0,0,this);
}
}
Output using Example Program
This Java applet implements double-buffering by making a call to a
Factory Method which returns an Image object.
Commentary on the Factory Method