Camillo Särs
Faculty of Computer Science
Helsinki University of Technology
Camillo.Sars-at-iki.fi
Petri Wessman
Faculty of Computer Science
Helsinki University of Technology
Petri.Wessman@hut.fi
Matti Halme
Faculty of Computer Science
Helsinki University of Technology
mhalme@cc.hut.fi
The book "Design Patterns: Elements of Reusable Object-Oriented Software" by Gamma, Helm, Johnson and Vlissides brings a fresh viewpoint to software design methodology. By concentrating on general patterns in object-oriented software design instead of language-specific concepts, the book gives a practical method for classifying and re-using software structures. In this paper, we examine the Abstract Windowing Toolkit (AWT) of the popular Java language in light of the Design Patterns methodology, and present as a case study a prototype application written using AWT and Design Patterns.
We set out to study how design patterns can be applied when working with the Java Abstract Windowing Toolkit (AWT). Studying design patterns as an abstraction is not nearly as useful as studying their application to real world problems. We chose Java because it is an emerging object oriented programming language which shows great promise for the future. [Java]
User interfaces are among the most important features of modern client-server applications. They are also probably the part that programmers tend to neglect the most. This neglect is possibly due to the complex nature of user interfaces, which for many programmers seems elusive. Toolkits for user interfaces allows the programmer to build the user interface framework in minutes, but designing the interface properly and understanding the entities at work in it requires much more time.
The Abstract Windowing Toolkit gives the programmer a possibility to construct a graphical user interface for a Java application. The abstraction level is low, however, and creating a working interface requires much more work than if the work was done using some more advanced tools, say Borland Delphi for instance.
In this paper we present our work with Java, the AWT and design patterns. We use the term "design patterns" here to mean the patterns presented in [DP].
As a language Java supports the Design Patterns model very well, as it supports inheritance (albeit only single inheritance at the moment) and interfaces. The java interface/implementation model is extremely useful in the Design Patterns context (and in general Java program design, as well).
Java and the associated class libraries (AWT and others) are still young, and although the language and the libraries on the whole are well designed, it is more than likely that they will evolve from their present form.
The AWT provides only "basic" GUI controls, leaving out the fancier controls found in many GUIs (tabbed notebooks, floating toolbars, etc). The intent of this is to maximize portability, but as a downside Java applications written using the AWT will look fairly "primitive" compared to native applications. This situation will probably be corrected in the future as Javasoft introduces an API for third-party GUI controls and advanced graphics [Beans, Beans2]. For the moment, however, Java designers will have to make do with the AWT and code the fancier display elements themselves.
Fig 2.1 Diagram of the java.awt class hierarchy
(Note: this notation uses solid arrows to represent inheritance and dashed arrows to represent (interface) implementation. A dashed box around a class means that it is part of another Java class library.)
The AWT divides GUI controls into "components" and "containers". Containers can contain components, and are themselves components (i.e. containers can contain other containers).
Four container classes are provided:
The major components which can be added to the above containers are:
This library also contains classes for the manipulation of different color models (RGB, DirectColor, etc).
Fig 2.2 Diagram of the java.awt.image class hierarchy
(same notation as previous class diagram)
This abstraction layer encapsulates the AWT components from operating system- or GUI-dependencies, it does not add (or remove) any functionality from the java.awt classes.
The main elements of the java.awt library are components and containers. Components have no clear pattern associated with them, but containers obviously represent the Design Patterns Composite pattern. The LayoutManager and its subclasses represent Strategy patterns, in that they implement various strategies for laying out components in a container, and the strategy can be changed "on the fly" without changes to the containers (or the components).
The other classes are less clear. Events can be seen as Command patterns, in that they have a state and lifetime that is separate from the originating event (mouse click, key press, etc). The MediaTracker class (which manages the loading of graphical, audio,, or other data) can be seen as a Mediator pattern controlling various sub-elements and making sure they function together. The Toolkit class is in some ways a Facade for various (potentially complex) operating system functions -- it can also be seen as an Abstract Factory for creating GUI-specific components (the so-caller AWT "peer" classes).
The main elements of the java.awt.image library are consumers, producers and observers. Observers have a clear counterpart in the Design Patterns Observer pattern, but producers and consumers are less clear. Producers are somewhat like the Factory Method pattern, but not quite since only one thing is produced (an image stream), and the producer and consumer are very tightly bound together -- no clear counterpart exists in Design Patterns. In the AWT producer/consumer relationship, the consumer registers itself to the producer, which calls methods in the producer to deliver data when data is available.
The other classes in java.awt.image consist of ColorModels, which provide a uniform interface to handle different color models. These can be seen as a Design Patterns Strategy, with each derived ColorModel class providing a different strategy for handling colors.
The java.awt.peer classes separate the actual implementations of the GUI elements from the "generic" interfaces and can be identified as pure Bridge patterns.
Design patterns are principles used in object-oriented software design, and are quite useless if they are not applied to some problem. To learn how to use design patterns, we decided to write a small application using the Java AWT. The program itself was not important, it was the application of design patterns to the process that was intriguing.
Would we be able to identify the problems we faced and apply the correct patterns to them? Is there a "correct" pattern? Could the Java AWT actually be used to build a "real" application? Would the AWT allow us to use the patterns we wanted, or would it force us to use the paradigm it stands for? These are only some of the questions we were faced with at the beginning of our work.
We chose to implement a database browser. The specifications we laid down were not very detailed, as we were not trying to make a production quality application. Rather we aimed at writing software using design patterns and learning something about patterns as well as the Java AWT. None of us was very familiar with Java, either, so we faced a real challenge.
The browser will resemble any ordinary Windows or X-Windows application. It shall have pull-down menus for commands and all the other familiar features of a windowed application. The main menus are
The main window of the browser shall consist of two main areas, divided by a vertical separator. The separator should be movable, so that the user can choose how the window is split.
The left pane is an outline. The main level of the outline shows any databases currently available. Existing databases can be added with the Add command and new ones created with the New command. The Open command opens the selected database, just like expanding it in the outline does. The Delete command is only available if the database actually can be destroyed.
The databases shown may be local databases or accessed over the Internet. The database layer creates an abstraction, so that the application seldom sees the differences. The database access protocols are outside the scope of our work; we simply assume they are available and create a suitable simulation.
Detailed information about the item selected in the outline is shown in the right pane. The outline levels are determined by the information available about a particular database, but all relevant information should be accessible. Typically the information is directly associated with the tables.
The right pane is divided horizontally into two areas, again so that the user can resize the areas at will.
Fig 3.1 UI prototype done in Windows
The main task was not even to complete the application, but to start working on it and learning on the way. For all we knew, the AWT may not even have been suitable for the task.
Some user interface elements can be found in the specification. They may exist in the AWT, but most probably need to be designed separately.
Designing the Database-browser application described above could be roughly divided into two parts : Designing the database-access system and designing the user-interface. Since we are mainly interested in applying design patterns into the design of an AWT-application, the main emphasis of this paper should clearly be in designing the user-interface.
However, a functionality of a user-interface can't be successfully demonstrated without suitable data. The database-access can't thus be totally forgotten in the design considerations. At the minimum a rough abstraction of a database system and a simple data simulation mechanism are needed at the first stage.
Adopting a Model/View/Controller-paradigm described in [DP] as a principle design-strategy of the application seems to be justified by the fact that one of the key properties of MVC is that it separates user-interface from the other parts of the application. In a Database-browser a set of databases or suitable abstraction of those clearly acts as the model-part of the application. The user-interface of the application forms both the view- and controller-parts of the application.
In AWT as in many other window-toolkits the window-objects or other visible user-interface components actually handle the user-input. This implies that the view- and controller-parts of the application tend to form a single entity. Separating view- and controller-parts can thus be very violent and unnatural approach in many applications. In the database-browser being implemented the separation of the view- and controller-parts is not considered very important, at least at this stage of design.
Using the MVC-model thus allows us to design the database-related and user-interface parts of the application separately. Abstraction of the set of databases as a model allows us to use a simulated database in the user-interface phase of the implementation and later replace the model part with actual database-access implementation having a identical interface.
The nature of the application being implemented requires different kinds of information being modeled consisting at least of :
Although each of these classes of data conceptually fall under single entity that could be called 'the set of available databases' for example, the nature and requirements of those two greatly differ. For example the database-hierarchy data-structure should support the ability to be viewed as a hierarchical outline-list found in the left-pane of the application's user-interface. On the other hand the actual database contents consists of table-entities not related to each other under the scope of this application. Also the objects modeling the contents of a table might need to perform database-queries and buffer large amounts of data. A database object should be able to query the set of tables and represent them as a simple-to-use data structure.
The next principal design decision implied by the concepts represented above is that should the model be implemented as one closely integrated data-structure or should each of the three be treated as individual entities. We believe that the latter strategy leads to better modularity hopefully leading to more flexible design.
Of course the hierarchy, database, and table closely relate to each other. Basically a hierarchy line has a one-to-one relationship to either a database or a table depending on the kind of the line. Also databases and tables have a one-to-many relationship to each other but under the scope of this application that relationship is not very important and is actually managed by the hierarchy object.
Since hierarchy items share many common properties but differ in
the kind of database-object they are related to, we decided to
subclass different hierarchy items from a common base class
BrowsableItem
. Since databases and tables don't
have much in common we decided not to subclass them from common
base-class.
As a result of these considerations, the following initial class diagram was drawn :
Fig 3.2 Database outline classes
The links between the browsable items and actual database-entities
actually form a Bridge-pattern represented
in [DP, p. 151].
The database hierarchy is an abstraction that is decoupled of the
database/table implementation by two bridges. As a consequence,
The data-access and hierarchy models can be developed and extended
independently from each other. Different data-access methods
including a simulated one mentioned earlier in this paper
can be implemented by subclassing Database
and
Table
classes.
The operations represented in the diagram are possibly incorrect and sure don't cover all the operations needed. These operations will be defined when the data-access and hierarchy models are more carefully designed at the rest of this chapter.
Database is basically a collection of tables and other information such as information of authenticated users of the database. Queries expressed as a query language such as SQL can be applied to a database to obtain a set of records as a result. Queries can also be processed to modify data of the database.
The application should be able to handle different kind of databases including :
Ideally different kinds of databases could be browsed with single
application. Since all kinds of databases can be made to look very
much alike, this goal could be achieved by subclassing different
database-implementation classes from the Database
-class
represented earlier in this paper. Since the implementation of
database is separated from its appearance in the outline-hierarchy this
can be done without any affect on the hierarchical model. The
following class diagram represents the different database-classes :
Fig 3.3 Database classes
It should be noticed, that operation getTables
doesn't
need to return actual table-objects but merely a set of table-names
of the database. Table objects don't need to be created until user
actually accesses a particular table of the database.
Different kinds of table-implementations form a similar class
hierarchy. Each class having a Table
-interface can return
all its record as a RecordSet
-object. A database object
processing a select-query written in SQL by the user also returns
a RecordSet
-object.
When accessing server databases, the recordset-objects shouldn't contain the actual data records, since it's very impractical to retrieve the contents of a large table or results of a query at once to be browsed possibly for the few first records only. Recordset-objects should thus support record-cursors available at most database server implementations. On the other hand, the practical way to implement a memory-database could be to have the recordset-objects contain the actual records. In a simulated database the records may be produced runtime. Yet the access of the records in each of these recordsets should be uniform so that a single view-component could be used to show all kinds of recordsets.
Fortunately we have heard of the Iterator-Pattern described in [DP, p. 257]. An iterator is meant to provide a uniform way to access the elements of heterogenous aggregate objects. Each implementation of recordset can thus have a different way to manage the storage of its records and provide an iterator sharing a common interface with other recordset-iterators.
We can then include a
We should also have another factory method to create the
correct table-implementation instances, when we have a specific
kind of database-implementation object. Method
One of the key functionalities offered by the database browser being
implemented is that it let's the user to look at available databases
as a simple uniform list. Any database can be opened by the user to
show the main level contents of that database. Main levels of a
contents of a database could be items like tables and users.
To fulfill these requirements and to ensure the flexibility and
extensibility, the database hierarchy model should have at least
the following properties :
It's not hard to see that a Composite-pattern
represented in [DP, p.163] can address these requirements.
Lines of the database-browser outline each form a Leaf- or Composite-
participant of the pattern. The outline view-object acts as a
Client-participant.
While further examining different items forming the database
browser outline, the items could be divided into composite
and leaf objects as follows :
In the original user-interface prototype table was a leaf, but we
decided to have a table item have it's data and structure as
children to avoid implementing a tabbed control on the bottom
part of the right pane.
Composite- and leaf-items have very much in common and the
requirements of uniform accessibility of the two makes separate
composite- and leaf-classes look very much alike. A composite pattern
could be implemented joining the leaf-, composite- and
component-classes into a single component-class.
This decision would not be
visible to clients at all and would have a little impact on the
internal structure of the database hierarchy model as a
composite-pattern. As a implementation issue it would
have following consequences :
The decision of the way our composite should be implemented is not
very easy one. The leaf-overhead probably isn't very important factor.
However, since this paper deals with design patterns we decided to
implement the database hierarchy model as a 'pure' composite-pattern
separating the leaf and composite implementations from each other.
The following class diagram was obtained :
Fig 3.4 Browsable item structure
As one can see from the diagram above there are two methods,
that return a set of other
A major problem in the user-interface design
for an AWT-application is that the set of graphical components or widgets
available by the AWT is clearly a narrow subset of those offered
by Microsoft Windows-based toolkits for example.
In order to be able to implement a graphical AWT-application with
the need of wide set of user-interface components, many components need to be
composed of more primitive components offered by AWT. This clearly increases the
amount of work when designing and implementing the application. On the other
hand when designing some components from scratch, the designer is given more
freedom to make certain design decisions that may have a positive impact on
the design of the application as whole. The component can be designed to
closely reflect the actual data structures and object-interaction semantics of
the actual application.
The user-interface design of the database-browser
can clearly be divided into following four parts corresponding
to the different visible areas of the main window of the application:
The menu system should act as a controller-object and
can be implemented directly using AWT.
The design of the hierarchical outline list of database-components
is based on the fact that the model consisting of the database items
offers a recursive iterator with the function
1-4 can be obtained directly form the database hierarchy model
described earlier. 5 can be calculated easily by maintaining a
loop counter during the drawing and multiplying value of it
with the height of a single item, which can be kept constant.
6 is required by the last siblings to draw a vertical line
back to its parent. Methods
A vertical scroll position of a scrollbar at the side of the view
can be taken into account by a simple coordinate transformation.
The SQL-entry panel can be implemented as a simple
AWT-
The results panel is basically a editable grid acting as a
view/controller-component. The results panel
is activated by the database-hierarchy model or SQL-entry
panel and is given a
The implementation of the Database-hierarchy model was quite
straight-forward. The child-management implementation was placed
at the
The storage of references to the children of
a composite was implemented as a simple linked list. All items
thus have a reference to the next sibling, if one exists. All
items also have a reference to their parents.
Java AWT doesn't have a component that could be used to view the
database hierarchy as the outline of the database browser. We had to
implement such a view from scratch subclassing the AWT
The screen shot below presents the database-browser when the
following parts of the application have been implemented :
Fig 3.5 Outline implemented in Java
Designing and implementing a non-trivial application with a graphical
user-interface using new tools such as Java programming language and
AWT-toolkit is an interesting experiment. Although fancy and
complex GUI-components are hard to implement with more
primitive components offered by AWT, we believe that they can be done.
The hierarchical outline-view seen in the application was actually
implemented using AWT.
Using the design patterns represented in [DP]
was believed to offer some widely used common solutions to certain
design issues faced when designing the application. We decided to
take the MVC-organization of the application
as the principal design strategy.
MVC is not a pattern itself, but a larger application-architecture that
can be designed and implemented largely using design patterns.
We hoped to be able to use some design patterns based objects
as building-blocks of a MVC-application.
The application was able to be designed based on MVC.
However, for very practical reasons, some of the view- and controller-parts
were integrated together. We finally ended up with design, that was
composed by interacting MVC-components and not just one of each kind
but several. The application contains two kinds of models :
a single database-hierarchy model and a data-access model
for each actual database-table to be viewed. The
data of these models can be represented and manipulated using two
view/controller-objects respectively:
a database-hierarchy view/controller and
a results grid. Additionally, a user can enter input
to the application with two controller-objects:
a SQL-entry panel and a menu-bar.
Since the database-hierarchy model, database-hierarchy view/controller
and the data-access model were more carefully
designed and also partially implemented we concentrate the
discussion of the use of the design patterns on them.
The design of the database-hierarchy model was based on the
composite, iterator and factory method patterns.
The model could be implemented in Java using these patterns in a very
straight-forward way.
The benefit of the patterns used in database-hierarchy model can
actually be seen in the database-hierarchy view/controller which
acts as a client participant of the composite pattern. We believe
that the visual representation was greatly simplified by the fact
that the model below offered a recursive iterator that could be
used to perform a depth-first traversal through all visible items in
the database-hierarchy. The property of the composite pattern
that all its items have a uniform interface made it possible
to implement such an iterator. The key idea of the composite
pattern indeed is that all items look very much uniform. The handling
of the user-commands in the form of catching
the mouse-clicks inside the view's area was also simplified
by the uniformity of the individual items.
The object-oriented design of the AWT supported the use of the
design patterns, since design patterns are heavily based on objects
and their collaborations. Participants of the design patterns
are usually objects (or objects take the role of possibly
several participants). AWT-derived objects can thus take
the role of a participant such as the client of a composite pattern.
In the case-study application the database hierarchy view/controller
was implemented as class
Also in the design of the data-access model, some patterns were utilized.
The different kinds of databases could be handled by the application
transparently and simultaneously, since all different
database-implementation classes share a common interface
The different database-table implementation classes also share a common
interface class namely
An iterator pattern was found to be a very nice solution in accessing
the individual records in a recordset representing the records of a
single table or results of a SQL-query.
We found that design patterns are very useful when designing an
application with a graphical user interface. The patterns provided us
with valuable information on what kinds of problems can occur and
offered solutions to most of them. The solutions were abstract enough
so that we could apply them to the Java AWT, yet concrete enough to be
clearly applicable.
Using design patterns in the UI design was more a state of mind than a
design methodology. We were all familiar with object oriented design,
but had seldom thought of objects at the level the design patterns
presented them. Once we understood the abstraction, we found it easy
to apply it to our design.
The design patterns describe interactions that occur between objects
in an application. We identified similar interactions in our design
quite early and were then able to consult the patterns for possible
solutions. Contrast this with the more "traditional" object oriented
design that concentrates on the objects, their properties and
relations to other objects. A relation between two objects does not
tell you as much as a description of the interactions between the two.
We chose Java and the AWT purely out of interest, and it proved a
valuable experience. Even though we did not investigate the Java
interface concept to its full potential, it is certainly a good tool
for pattern based design. Objects that participate in several
patterns in different roles can easily be designed using the interface
definitions. One could even claim that some patterns can be implemented
using nothing more than interface definitions, but then the
interactions would have to be described informally or some of the
value of the patterns would be lost.
GUI based applications exhibit common features that can easily be
designed using patterns; one might say that many of the tools of GUI
design actually "instantiate patterns" in different configurations.
This is not quite true, however, as pattern based design requires a
conscious effort to identify and utilize patterns. After all, what
are patterns but a pool of collective expertise that expert designers
use in their designs.
getRecords
-method
to the RecordSet
-interface. Method getRecords
forms a Factory Method-pattern described in
[DP, p.107]. Each recordset-implementation overrides
this method to return the correct iterator.
createTable
should thus be included into the Database
-interface.
Database hierarchy model
BrowsableItem
objects:
getChildren
and getDescendants
. These
methods will actually return return objects belonging
to Iterator-Pattern
described in [DP, p. 257]
namely objects of classes DBItemIterator
and
RecursiveDBItemIterator
respectively. The methods
returning the iterators act as FactoryMethods
[DP, p.107] allowing possible new subclasses
to have their own child-set implementations and iterators
collaborating with them.
Designing the user-interface
getDecendants
. While iterating the hierarchy each item
can be drawn if the following information is available :
getParent
,
and getNextSibling
can easily be included into
BrowsableItem's
interface. A method
getRow
returning the number of the row a item
is at should also be implementable using a recursive
iterator for example. 6 can thus be calculated.
Panel
containing two Button
s
and one TextArea
. The role of the panel
in MVC-architecture is clearly a controller.
RecordDef
, or RecordSet
as a document
to be viewed and/or edited. The role of the grid
in MVC-architecture is a mixed view/controller.
The actual detailed design and implementation of such a grid is far
beyond the resources of this project.
3.3 Implementation
CompositeItem
-base-class instead of the
individual CompositeItem-derived
classes. This
implies that the child management is implemented identically
in all composite items. However different set-implementations
for example can be done by adding the child-management-code
into the derived class, implementing new iterators and overriding the
getChildren
and getDescendants
-methods.
Canvas
-class and overriding the
paint
-method. The Database-hierarchy view/controller
could thus be implemented using the functionality of the
database-hierarchy-model and a fairly small subset of AWT-graphics
primitives. Handling of the mouse-operations were implemented through
overriding the MouseDown
-method.
MemDB
-implementation of the
data-access model
SimulatedDB
-implementation
of the data-access model
3.4 Analysis
DBCanvasList
derived from AWT-class Canvas
.
Database
. The links between the database-items in the
database hierarchy and the corresponding database-implementation
objects form a bridge-pattern. The use of bridge allows the
separation of the hierarchical database model from the implementation
and thus simplifies the transparent and simultaneous access of
heterogenous databases.
Table
.
The instantiation of the implementation-specific table
classes was abstracted by a factory method -pattern. A table-object
belonging to a specific database-implementation could thus be
uniformly created by calling the createTable
-method of
that database-instance.
4. Conclusions
References
"Design Patterns: Elements of Reusable Object-Oriented
Software",
1994, Addison-Wesley Publishing, ISBN 0-201-63361-2
http://java.sun.com/.
http://www.javaworld.com/javaworld/jw-09-1996/jw-09-javabeans.html
http://splash.javasoft.com/beans/
Glossary
AWT Abstract Windowing Toolkit,
an object-oriented GUI API for Java-programs, shipped with the JDK.
GUI Graphical User Interface.
API Application Programming Interface.
JDK Java Development Kit, a
distribution released by SunSoft containing the Java compiler, the
Java interpreter, the Java libraries and some additional utilities.
MVC Model/View/Controller, a way
to organize an interactive application into three parts, each
implementing certain responsibilities.
$Revision: 1.14 $ $Date: 1996/09/02 17:46:49 $
Last modified: Mon Sep 2 20:44:52 1996