Saturday, April 5, 2008

Solution to one Design Puzzle in Head First Design Pattern

I am reading Head First Design Pattern. It is a great book.

Generally, I don't like exercises in a book which don't have answers provided. I have run into the design puzzle on page 468. At first sight, I knew that I should use state pattern. I have never applied state pattern in real software work before. So I took this exercise as an opportunity to practice state pattern. Here is my solution.

State.java

package headfirst.proxy.virtualproxy;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public interface State {
public int getIconWidth();
public int getIconHeight();
public void paintIcon( Component c, Graphics g, int x, int y );
}

NullState.java

package headfirst.proxy.virtualproxy;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class NullState implements State {

private ImageProxy proxy;
private Thread retrievalThread;
private URL imageURL;
boolean retrieving = false;

public NullState( ImageProxy p, URL url) {
proxy = p;
imageURL = url;
}

public int getIconWidth() {
return 800;
}

public int getIconHeight() {
return 600;
}

public void paintIcon( final Component c, Graphics g, int x, int y ) {
g.drawString("Loading CD cover, please wait...", x+300, y+190);
if (!retrieving) {
retrieving = true;
retrievalThread = new Thread(new Runnable() {
public void run() {
try {
ImageIcon imageIcon = new ImageIcon(imageURL, "CD Cover");
proxy.setState( new ImageState( imageIcon ) );
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}

ImageState.java

package headfirst.proxy.virtualproxy;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ImageState implements State {

private ImageIcon imageIcon;

public ImageState( ImageIcon i ) {
imageIcon = i;
}

public int getIconWidth() {
return imageIcon.getIconWidth();
}

public int getIconHeight() {
return imageIcon.getIconHeight();
}

public void paintIcon( final Component c, Graphics g, int x, int y ) {
imageIcon.paintIcon(c, g, x, y);
}
}

ImageProxy.java

package headfirst.proxy.virtualproxy;

import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ImageProxy implements Icon {

private NullState ns;
private State state;

public ImageProxy(URL url) {
ns = new NullState( this, url );
state = ns;
}

public int getIconWidth() {
return state.getIconWidth();
}

public int getIconHeight() {
return state.getIconWidth();
}

public void paintIcon(final Component c, Graphics g, int x, int y) {
state.paintIcon( c, g, x, y);
}

public void setState( State s )
{
state = s;
}
}

1 comment:

Kaizar said...

That's a perfect soultion, thanks for sharing.