Composite pattern: Printing in JavaPosted on 10 November 2012 in Patterns applied
At school we were building a system in Java that involved invoices. One of my tasks was to design and build a invoice viewer and printer. I applied the composite pattern here because i thought it was fitting and because i wanted to implement it in a "real" application.
In this post i will not focus on the actual printing part. In short i implemented the Printable interface for the drawing part, and implemented Runnable as to not block the application with the long running printing process.
To print something with Java you use the Graphics2D class to draw what ever it is you want to be printed. When doing so you specify exact 2D coordinates. So lets say you have 100 shapes: text blocks, lines, images, etc, all positioned with hardcoded coordinates it will be verry hard to change anything.
The composite pattern can help here to define a hierarchy of shape components. This hierarchy then gets the responsibility to draw itself recursively. The hierarchy will consist of composite components like tables, and leaf components like text blocks. If each leaf knows its size as a rectangle than all other coordinates and sizes can be calculated when traversing the composite structure. Figure 1 displays the UML diagram.
Drawable This is the component class. It defines a origin property which is the top left position and a size property. The abstract draw method must be implemented by concrete Drawables.
Table Composite component. The Table class contains a 2D array of Drawables. The draw method will delegate the request to each Drawable in the table. A Table object knows the dimensions of its rows and columns and will modify the Drawables by setting its size property so it fills the whole cell. Also responsible for calculating the origin property of each Drawable in the table.
Ruler and TextBlock Leaf components. Responsible for drawing a horizontal line and text.
Below is the code that creates the component hierarchy. Its still alot of code but it is far more maintainable than hardcoding all the coordnates. The system also allows you to add new Drawables when they are needed.
Figure 3 shows what happens when calling the layoutTable.draw and passing in the Graphics object from a JPanel.
- Source code Java source (NetBeans project)