Introduction

Container-Component

MenuComponent - MenuContainer

Component-Peer

LayoutManager

Graphics

FocusManager

ImageObserver

ImageProducer-ImageConsumer

References

Design Patterns in Java AWT

Introduction

Design Patterns

A pattern describes a problem which occurs over and over again, and then describes the core of the solution to that problem in such a way that you can use this solution without ever doing it the same way twice.

In general, pattern has four essential elements: [Gamma95]

1. The pattern name is a handle we can use to describe a design problem.

2. The problem describes when to apply the pattern.

3. The solution describes the elements that make up the design, their relationships, responsibilities, and collaborations.

4. The consequences are the results and trade-offs of applying the pattern.

More about Design Patterns on Patterns Home Page

Many FAQs about Design Patterns are answered in Patterns FAQ

which is maintained by Doug Lea

Also, there are some examples of Design Patterns

About Java

Java is a new and very attractive object-oriented programming language. Its advantages include simplicity (compared to C++), strong types, automatic memory management, and support for interfaces. The latter is especially useful when the Role Modelling [OOram] approach is exploited.

An interface encapsulates a coherent set of services and attributes (broadly, a Role), without explicitly binding this functionality to that of any particular object or code.

Interfaces are “more abstract” than classes since they do not say anything at all about representation or code. All they do is describe public operations. For example, the java.lang.Runnable interface is just:

public interface Runnable {

public abstract void run();

}

More about Java

Some aspects of Java interfaces: [Lea96]

Seminar work

This paper is written as the work for course “Design Patterns” Tik-76.278 “Ohjelmoinnin Seminaari”

http://mordor.cs.hut.fi/tik-76.278/

We tried to reverse engineer the Java AWT package, mainly attempting to use the Role Modelling approach [OOram] , and looking for design patterns described in [Gamma95].

Patterns in Java AWT

Container- Component

Area of concern

Visual components' tree structure, focusing on the parent child pair.

Class structure (Composite pattern, Gamma pg. 163)

A generic Abstract Window Toolkit(AWT) container object is a component that can contain other AWT components.

Roles and responsibilities

Container -- it represents the parent object in visual component hierarchy. It is a visual component that contains sub-components and delegates some its functionality to its children.

Component -- has characteristics of child object in visual components tree structure. May inherit some characteristics from its parent.

Interface description

interface Component< Container

addNotify()

Notifies the Component to create a peer (a platform and look-and-feel specific peer object) and propagate peer creation down the containment hierarchy.

removeNotify()

Notify the Component to destroy the peer and propagate peer destruction down the component hierarchy

setParent(Container)

Container getParent()

Set and get the Components parent.

validate()

Validates (lays out) the component if necessary. Propagates the call to all sub-components.

paintAll(Graphics)

Paints the component and its sub-components on the given Graphics context.

Rectangle bounds()

Returns bounding rectangle of the component.

boolean inside(int x, int y)

Determines if the specified location is inside this component.

interface Container< Component

postEvent(Event)

Posts event up the containment hierarchy, thus allowing each object in the chain to handle the event.

invalidate()

Popagates the invalid state up to containment hierarchy.

boolean isShowing()

Propagates the isShowing query up the containment hierarchy.

Color getForeground()

Color getBackgound()

Font getFont()

The component may inherit its foreground and background color, and its font from its parent, when not explicitly set for this component.

setFocusOwner(Component)

nextFocus(Component)

Propagate focus information up the containment hierarchy.

Use of Chain of Responsibility (event handling, getFont, getBackgroundColor,…)

Scenarios

This scenario illustrates how the component inherits its font from its parent when not explicitly set.

The following scenario illustrates how the validation is propagated down the containment hierarchy and how the validation causes the component being laid out.

MenuComponent - MenuContainer

Area of concern

Parent-child relationship in a hierarchy.

Roles and responsibilities

MenuComponent - Child object in a menucomponents hierarchy

MenuContainer- Parent object that can contain MenuComponents.

Collaborations

MenuContainer can contain MenuComponents. It is responsible for notifying its components to create and destroy peers - the platform specific implementations. MenuComponent forward user events to its parent, and it may inherit its font attribute from the parent.

Class and interface hierarchy

Class (illustrates how different classes can play several roles by implementing Java interfaces)

Here the grey rectangle represents a Java interface and the transparent rectangles represent Java classes. So the MenuContainer interface(role) can be implemented(played) by classes from separate parts of the class inheritance hierarchy.

Component-Peer

Area of concern

Platform independent components implementation using the platform specific (and look-and-feel specific) visual components.

Roles and responsibilities

Component - an abstract (platform and look-and-feel independent) visual component.

ComponentPeer - role of platform specific visual component which supports set of primitive operations on it.

Collaborations

Component forwards client requests to its peer. It also caches its attribute values (font,foregroundcolor) and allows to modify these even when the peer doesn’t exist.. (So there is no get methods, except getGraphics, defined in the ComponentPeer interface. ) This makes possible to defer the peer creation until the component is first shown.

Corresponding to the Bridge pattern the ComponentPeer (Implementor) does provide only primitive operations and the Component (Abstraction) defines (adds) some higher-level operations as paintAll and layout. The paintAll operation paints the component and its sub-components, and the layout operation lays out the component, generally by moving and resizing the sub-components.

The peer is responsible of forwarding user input events to its component through the postEvent call.

Component-peer as an instance of Bridge pattern.

The components and peers form separate class/interface hierarchies. Every AWT component sub-class has its corresponding peer sub-interface with which it can communicate. So here is one more inheritance dimension compared to pure Bridge pattern. There are platform specific (and possibly specific to certain look-and-feel standards) classes that implement the peer interfaces.

The following figure illustrates a part from parallel class and inheritance hierarchies.

Creation of peers as Abstract Factory

The peer creation interface is defined by an abstract class, called Toolkit. Toolkit interface defines a peer creation method for each AWT component class. A concrete subclass of Toolkit implements the creation of a certain platform (or look-and-feel) specific peers. Default Toolkit class is determined by the Java system properties.

This creation method corresponds exactly to the Abstract Factory design pattern.

LayoutManager

Area of concern

Encapsulating of the layout algorithm.

Roles and responsibilities

Container - an object that needs to lay out its sub-components.

LayoutManager - an object that encapsulates the layout algorithm

Component - an object which position and size is calculated during the layout operation

As Strategy pattern

This role model implements exactly the Strategy design pattern.

Scenario

Graphics

Area of concern

Encapsulation of the drawing context (Graphics) and separating roles for creating it, setting it up, and drawing on it.

Roles and responsibilities

Creator - object that creates drawing context for a specific device

Director - the one who sets up the coordinate system and the clipping region for another object to draw into.

Drawer - object that draws on a drawing context set up for it.

Graphics - encapsulates the drawing context., maintains clipping area, coordinate origin, current font, and color.

Roles in AWT

In Java AWT visual component hierarchy composite components (Containers) usually play the Directors role as they set up the Graphics context for their children. Leaf components (subclasses of Canvas) usually may play the Drawers role. Some Container objects may play also Drawers roles (e.g. drawing borders). The Creators role is played somewhere inside the Java platform specific implementation.

FocusManager

Area of concern

Encapsulation of a role that maintains the current focus and handles the moving of the focus to next (or previous) leaf component.

Roles and responsibilities

FocusManager - the object that maintains the reference to the component having focus and knows how to move the focus forward or backward.

Component - the object in a hierarchy that can potentially be focus owner.

Client - the user (at least indirectly), who sends the focusNext, focusPrevious requests (for example using TAB and SHIFT+TAB keys)

This is an simplified (or “idealised”) role model in the sense that in the actual system the Components doesn’t send directly messages to the FocusManager. The messages are actually sent up the containment hierarchy and then forwarded to the FocusManager by Window (the top level component) as also seen from the scenario that follows. In this simplified form the roles correspond quite closely to the Mediator pattern.

In its original from these collaborations correspond also to the Strategy pattern as the Window encapsulates the focus managing algorithm into the FocusManager class.

Scenario

After the client sends the focusNext (or focusPrevious) message, the FocusManager looks for next focus candidate in the visual component hierarchy. Then it sends the requestFocus message to the candidate. If this message returns FALSE the FocusManager looks for another candidate, otherwise the clients request is completed. The component after receiving the focus sends the setFocusOwner message to the FocusManager, who registers then the new focus owner .

ImageObserver

This pattern is different from Gamma’s Observer in that there is only one observer, i.e. the application field of the pattern is more concrete, usually used for image transformation.

Motivation

When image is constructed asynchronously (and probably in the distributed applications), there sometimes is need to take actions when more information about image becomes available.

Structure

Participants

Graphics (Image)

- attaches an observer upon call to drawImage(). There is one ImageObserver. The image observer will be notified about Image state changes (e.g. the information about an image which was previously requested using an asynchronous interface becomes available).

ImageObserver

- defines an asynchronous update interface for receiving notifications about Image information as the Image is constructed

Collaborations

ConcreteGraphicsObject hooks ConcreteObserver when image update routine drawImage() is called. The ConcreteObserver gets information about Image later when this information becomes available.

ImageProducer- ImageConsumer

A pattern about Producer-consumer relationship is not described in Gamma, but it may be worth of some interest.

Motivation

In the distributed system the producer (transmitter of data/signals) and consumer may reside in different sub-systems, which may be integrated not so tightly. Producer-consumer pair abstraction may hide some methods/functions that are needed for synchronization, but not very important for higher levels of application.

In Java, there is ImageProducer and ImageConsumer interfaces.

Role model

Structure

Participants

Producer, Consumcer

Abstract base classes.

The Consumer has some similarities to Gamma’s Observer.

ImageProducer

The interface for objects which can produce the image data for Images. Each image contains an ImageProducer which is used to reconstruct the image whenever it is needed.

ImageConsumer

The interface for objects expressing interest in image data through the ImageProducer interfaces.

Collaborations

addConsumer() is used to register an ImageConsumer with the ImageProducer for access to the image data during a later reconstruction of the Image. The ImageProducer may, at its discretion, start delivering the image data to the consumer using the ImageConsumer interface immediately.

When a consumer is added to an image producer, the producer delivers all of the data about the image using the method calls defined in this interface.

The imageComplete method is called when the ImageProducer is finished delivering all of the pixels that the source image contains, or when a single frame of a multi-frame animation has been completed, or when an error in loading or producing the image has occurred. The ImageConsumer should remove itself from the list of consumers registered with the ImageProducer at this time, unless it is interested in successive frames.

Conclusion

In this paper we tried to study the design of Java AWT focusing in interesting object collaboration structures (trying to use the Role Modeling approach) and finding the correspondence to [Gamma95]’s design patterns. In no means is the result exhaustive.

References

[Gamma95] Gamma E., Helm R., Johnson R., Vlissides J. Design Patterns. Elements of Reusable Object-Oriented Software. Addison-Wesley 1995

[Lea96] Doug Lea. Implementing Design Patterns in Java.

Ooram] Reenskaug, T. Working with Objects. The Ooram Software Engineering Method. Manning Publications 1996. Foreword