The facade seen in the previous post has only an interface with its methods. It is also possible to enrich a facade with additional interfaces, connected to each other by various means. To illustrate it, I propose to add image management. This addition also makes it possible to present another design pattern: the Factory Method Pattern.
This post is part of the AWT GUI Facade series.
In graphic libraries, it is generally not possible to directly access the raw data of an image, it is always necessary to go through an identifier or a class to apply some processing. Knowing this, a relevant approach is to encapsulate what makes it possible to process the image in a dedicated class, for example:
Compared to the previous post, the following methods have been added to the GUIFacade interface:
createImage()
method creates an Image from the name of a file. In doing so, we are using the Factory Method pattern, which allows us to abstract the creation of objects, and whose creation process depends on inheritance. In this case, the user of the createImage()
method does not know which implementation of the Image interface will be used. This choice depends on the class that implements GUIFacade``
interface, whose details are not necessarily known to the user, since it is a facade.drawImage()
method is used to draw an image at (x, y) coordinates. Other methods dedicated to the creation and processing of images can be imagined, these are only examples among others.
The Image interface is used to represent access to an image managed by the graphics library. Methods can be proposed to work with an image. In our example, the getWidth()
and getHeight()
methods return the width and height of the image. Other methods can be imagined, such as a draw()
method that would draw the image, instead of the one within the GUIFacade interface.
For the implementation of the facade, we still use the AWT library. For the Image interface implementation, an AWTImage
class is proposed:
public class AWTImage implements Image {
private BufferedImage image;
@Override
public int getWidth() {
if (image == null) {
throw new RuntimeException("The image was not loaded");
}
return image.getWidth();
}
@Override
public int getHeight() {
if (image == null) {
throw new RuntimeException("The image was not loaded");
}
return image.getHeight();
}
void loadImage(String fileName) {
try {
image = ImageIO.read(this.getClass().getClassLoader().getResource(fileName));
} catch (IOException ex) {
throw new RuntimeException("Error when reading "+fileName);
}
}
void draw(Graphics graphics,int x,int y) {
graphics.drawImage(image, x, y, null);
}
}
The AWTImage
class holds an image reference to a java.awt.image.BufferedImage
. getWidth()
and getHeight()
methods return the width and height of the image. The other two methods are not part of the facade, and are invisible to its users. They are used by the AWTGUIFacade
class to load the image (loadImage()
method) and display it in a java.awt.Graphics (draw()
method):
public class AWTGUIFacade implements GUIFacade {
...
@Override
public Image createImage(String fileName) {
AWTImage image = new AWTImage();
image.loadImage(fileName);
return image;
}
@Override
public void drawImage(Image image, int x, int y) {
if (!(image instanceof AWTImage))
throw new IllegalArgumentException("Invalid image type");
AWTImage awtImage = (AWTImage) image;
awtImage.draw(graphics,x,y);
}
}
This new version of the facade can be used in the following way to display a window with an image:
public static void run(GUIFacade gui) {
Image titleImage = gui.createImage("title.png");
gui.createWindow("AWT Graphic User Interface Facade",
titleImage.getWidth(),titleImage.getHeight());
while(!gui.isClosingRequested()) {
if (gui.beginPaint()) {
gui.drawImage(titleImage,0,0);
gui.endPaint();
}
}
gui.dispose();
}
The image is created from the file "title.png" (1. 2), a window of the size of the image is also created (l.3), and as long as the game is not finished (l. 5), the drawing is started (1. 6), the picture is displayed (1. 7) and the drawing is ended (1. 8).
The code of this post can be downloaded here:
To compile: javac com/learngameprog/awtfacade03/Main.java
To run: java com.learngameprog.awtfacade03.Main