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;
}
}