Design Pattern Examples

The experiments discussed in this chapter involve a total of seven design patterns, sometimes in combination: Abstract Factory, Bridge, Compositum, Decorator, Observer, Template Method, and Visitor. Observer is a nice one to discuss in some detail; the rest will be characterized briefly. Exact specifications appear in [Gamma et al. 1995].

The Observer pattern solves the following design problem. Suppose an application contains an important data structure that is updated repeatedly. This data structure is called the subject. Suppose furthermore that there are a number of other components that need to be informed whenever the subject changes. These are called observers, because they watch the changes to the subject. An important aspect is that it is unknown how many observers there will be: observers should be independent and be able to come and go. This aspect precludes bundling the subject with the observers into a single class or module. Instead, there must be a dynamic link between subject and observers. The solution to this design problem is as follows: Both subject and observers are independent objects, and observers interested in a subject must register at the subject. When the subject changes, it sends a message, or an alert, to all registered observers. An example of the Observer pattern is a blog that readers might be interested in. Rather than monitoring the blog continuously, readers register at the blog and receive an alert—for example, an email message or notice in a message window—when a new blog entry has been added. Readers can then decide when to fetch and read the new entry.

Figure 22-1 shows the class diagram for the Observer pattern. Both the subject and observer classes have concrete subclasses, indicating that the pattern must be adapted to given circumstances. The observer class provides three important methods. The methods attach and detach are meant to register and deregister observers. The method notify goes through the list of observers and calls the function update on every registered observer. Each concrete observer class implements its own version of update. Each update method simply fetches relevant data from the concrete subject and updates its own variables. The important property of this pattern is that observers are independent of each other (no observer needs to pass data to another), but whenever the subject changes, all registered observers are updated automatically.

Observer design pattern (adapted from [Gamma et al. 1995])

Figure 22-1. Observer design pattern (adapted from [Gamma et al. 1995])

Abstract Factory, also known as Kit, provides a mechanism for creating sets of matched objects. For example, consider the elements of a user interface toolkit, such as windows, buttons, scroll bars, icons, etc. When a user interface is initialized, it is necessary to select implementations of the graphical elements that are matched to the platform. To do so, one uses a factory object that delivers the right graphical elements for a given platform. If the platform changes, one chooses a different factory. All factories have the same interface specified in an abstract class, hence the name of the pattern. The advantage is that the program setting up a user interface needs to select the appropriate factory once, while the rest of the program is written independently of the actual choice by always going through the factory.

Bridge is also a pattern for handling different platforms. Suppose again that developers plan to build a user interface toolkit that runs on several platforms. Suppose furthermore that they decide to build all user interface elements from scratch, without using the native elements of the platform. To draw these elements, several primitive drawing operations are needed, such as drawing lines, drawing text, or setting colors. The Bridge pattern says to collect these primitive operations into an interface, and then to implement this interface on several platforms. When initializing the toolkit, select the implementation appropriate for the platform and store a pointer to it in every interface element. When it becomes necessary to draw a button or window, all calls to the primitive drawing operations will go through this pointer to the implementation chosen for the given platform. This pointer is the “bridge” that connects the interface elements with the platform-specific primitives.

Composite is used to construct parts hierarchies. The filesystem of a computer is a parts hierarchy: a root directory contains files and directories, the contained directories in turn list files and other directories, and so on. A parts hierarchy may cascade to arbitrary depth. The Composite pattern provides a standardized way to arrange such hierarchies. It distinguishes container nodes (in our example, the containers would be the directories) and leaf nodes (files in our examples). Leaf nodes are atomic, meaning they cannot contain other nodes. The interfaces of containers and leaves offer operations that are common to both. In our example, some of the common operations are renaming, moving a file or directory to another directory, or opening a file or directory.

Decorator is useful for adding information or functionality to an existing class, without modifying the class. A Decorator is a proxy that is used instead of the original. Whenever a decorator object receives a message, it executes its own function and then delegates to the original. For instance, a test decorator adds code that is executed before and after a test case is run, recording the identity of the test and its results.

Template Method is used to build extensible software. A template method is a larger function that calls helper methods, so-called hooks. Hooks are abstract, i.e., not implemented in the class defining the template. Subclasses of the class with the template method must provide these plug-ins. An Internet browser is a good example. It provides a method for playing media files, but this method must be extensible so that additional, unknown formats supplied by other manufacturers can be handled. The template method in the browser loads the media file, but provides hooks for playing, stopping, or rewinding. These hooks are then added later in the form of a subclass for each media type. The template method handles all organizational aspects of media files, but when it comes to playing the media, it delegates to the play method of the appropriate plug-in.

Visitor provides a bundle of methods that are used to walk a recursive data structure. Typically, Visitor is used together with Composite. For instance, a visitor for a file system might walk the directory tree to compute the space used by files and directories. Another visitor might extract keywords from files and enter them into an index that is used to find files that contain certain keywords. The interesting part of the Visitor pattern is that the visit-functions are not built into the Composite, as one would expect. Instead, a visitor can be built independently and “thrown at” a recursive data structure to traverse it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.114.28