Appendix D: Design Patterns

Home - About » Computer Science - Research - Dissertation
Computer Science
Research, Industry Work,
Programming
Community Service
Hillside Group, CHOOSE,
Stanford GSA
The Serious Side
Business School,
Learning Chinese
Humorous Takes
Switzerland, United States,
Software, Fun Photos
Travel Stories
Europe, United States, Asia
  
Living Places
Berlin (+ Gallery), Zürich
Boston, S.F. + Bay Area

This appendix describes several design patterns that are used in the main body of the dissertation using a role model form. The patterns are essentially the same as found in their original documentation, except that the role model form portrays them in a different light. The use of role models lets us more flexibly assign role types to classes than the class-based form allows us to do. While the class diagrams of the patterns frequently might look simpler than the role model diagrams, this is not the case. The complexity of a pattern is always the same, independently of its presentation form.

The pattern descriptions in this appendix have the following properties:

  • The descriptions of the patterns are incomplete. They merely serve as a reminder for those who forgot or do not know a specific pattern under the given name so they can quickly look it up. For a more detailed description, references are provided.
  • The patterns are illustrated rather than rigidly defined. There is no design pattern notation behind the pattern descriptions except than an intuitive understanding about what the role model illustration might communicate to developers regarding the pattern instantiation.
  • None of the descriptions is to be taken as a rigid definition. (See the discussion of pattern vs. template in Chapter 3). Role models are more flexible than class model and suggest a wider application [Rie96a], but even they cannot encompass all possible design templates.

In the diagrams, some role types and object relationship descriptions are grayed out. These role types are required in an instantiation of a pattern, but are not considered to be an integral part of the core pattern role model illustration. The primary example of such a grayed-out role model is the role type pair (Client, Object) that simply states that an object provides some domain functionality to a Client.

D.1 Abstract Factory

The Abstract Factory pattern centralizes the creation of objects from a family of products in a Factory object. A Client requests new Product objects from a Factory object. The Factory object ensures consistency among a family of Product objects and hides the details of the object creation process.

Figure D-1: Role model of the Abstract Factory pattern.

A class-based description of this pattern can be found in [GHJV95].

D.2 Adapter

The Adapter pattern adapts an existing object to a new use-context by means of an intermediate Adapter object. A Client uses the Adapter operations only, and the Adapter implements them in terms of the domain functionality of the Adaptee.

Figure D-2: Role model of the Adapter pattern.

A class-based description of this pattern can be found in [GHJV95].

D.3 Bridge

The Bridge pattern splits the implementation of a domain concept into an Abstraction and an Implementor object so that both can be varied independently. The Abstraction provides the primary domain functionality, and the Implementor provides the implementation primitives all variations of the Abstraction can be implemented by. The Client makes use only of the Abstraction. The Abstraction owns its Implementor, uses its operations for its own implementation, and hides it from the Client.

Figure D-3: Role model of the Bridge pattern.

A separate Client (not shown in the figure) configures the Abstraction with its Implementor. A common type of Client is an Abstract Factory that returns a preconfigured Bridge upon Client request.

A class-based description of this pattern can be found in [GHJV95].

D.4 Chain of Responsibility

The Chain of Responsibility pattern determines the target object of a client request dynamically by passing the request along a chain of objects. Each object in the chain may decide whether to execute, drop, or pass on the request. A Predecessor forwards the request to its Successor.

Figure D-4: Role model of the Chain of Responsibility pattern.

Using an object chain this way lets us configure the recipient of the request dynamically. A separate client configures the chain of objects.

A class-based description of this pattern can be found in [GHJV95].

D.5 Class Object

The Class Object pattern provides functionality common to all objects of a class in one Class object. A Class object can be asked for meta-information about any of its Instance objects. In contrast to a Type object, the Class object provides not only operations to inspect its Instances and provide information about it, but also functionality to create and change its Instances.

Figure D-5: Role model of the Class Object pattern.

Type Object is one element of the pattern triple Metaobject, Type Object, and Class Object. The distinction between Class Object and Type Object is done pragmatically. Class Objects provide implementation information about its Instances and they can manipulate and create Instances. Type Objects provide application domain specific information rather than implementation information; their implementations may be heterogeneous, and they cannot manipulate their Instances.

To my knowledge, there is no commonly known class-based description of the pattern. However, any major object-oriented system provides an implementation of this pattern.

D.6 Composite

The Composite pattern determines how to build a hierarchy of objects. Any object in the hierarchy is a Child, or a Parent, or both. A Child may receive a Parent object, and a Parent object may receive or drop some Child objects. The Child and Parent role types serve to configure and maintain the hierarchy. A Client configures a Parent with its Child objects.

Figure D-6: Role model of the Composite pattern.

A class-based description of this pattern can be found in [GHJV95].

D.7 Decorator

The Decorator pattern lets us transparently add functionality to an existing object through object composition. A Core object is wrapped by a Decorator object. The Client makes use of both the Core and the Decorator without seeing to different objects.

Figure D-7: Role model of the Decorator pattern.

A class-based description of this pattern can be found in [GHJV95].

D.8 Factory Method

The Factory Method pattern puts the creation of an object in method of its own that can be varied independently from the Client using the method. The Factory Method is provided by a Creator object that returns a Product object upon Client request.

Figure D-8: Role model of the Factory Method pattern.

A class-based description of this pattern can be found in [GHJV95].

D.9 Manager

The Manager pattern puts the management of some Elements into a Manager object so that Element management gets independent of the Client and the Elements. Clients request Elements from the Manager. The Manager owns the Elements. It creates, provides, and deletes them.

Figure D-9: Role model of the Manager pattern.

In [Som98], Sommerlad describes a class-based variant of this pattern, also called Manager. Sommerlad's Manager requires the set of Elements to be homogeneous, while the definition of Manager here accepts a heterogeneous collection of Elements.

D.10 Mediator

The Mediator pattern centralizes the communication of a set of Colleague objects in one Mediator object. The Colleagues do not communicate with each other directly, but only through the Mediator. This reduces communication complexity from square(n) to n. It facilitates the introduction and removal of a new Colleague object without affecting the other Colleagues.

Figure D-10: Role model of the Mediator pattern.

A class-based description of this pattern can be found in [GHJV95].

D.11 Metaobject

The Metaobject pattern separates the domain-specific functionality of an object from the technical procedure of executing this domain functionality. Clients send requests to the Metaobject for execution on a specific BaseObject. The Metaobject defines the procedures for executing incoming requests, and the BaseObject provides the functionality to invoke the domain-specific operations. The Metaobject typically deals with issues like request queuing and synchronization, and the BaseObject provides a dynamic invocation interface for calling the domain-specific operations.

Figure D-11: Role model of the Metaobject pattern.

The configuration of the Metaobject can be complex (see Chapter 6 for an example). Metaobjects are part of a metalevel architecture that represents the overall (conceptual and/or technical) framework for handling metalevel issues.

Metaobject is one of the pattern triple Metaobject, Type Object, and Class Object.

To my knowledge, there is no commonly known class-based description of the pattern. However, every object-oriented system based on an explicit metalevel architecture is likely to feature an instance of this pattern.

D.12 Null Object

The Null Object pattern serves to provide a null implementation of a domain concept. The null implementation provides null behavior, which is the behavior assumed to be executed if no object were present at all. The pattern lets developers set an object reference to the null object rather than to a null reference and avoids cluttering the client code with checks whether the reference is null or not.

Figure D-12: Role model of the Null Object pattern.

In [Woo98], Woolf describes the Null Object pattern. Because it is only about implementation, the pattern cannot be expressed well using role modeling.

D.13 Object Registry

The Object Registry pattern centralizes access to a set of Element objects in one Registry object. Clients register and unregister Elements at the Registry giving them convenient names for later retrieval. Such a Registry is typically a thread-local or process-local Singleton.

Figure D-13: Role model of the Object Registry pattern.

The Object Registry pattern is to be distinguished from the Value Registry pattern (not documented here). An Object Registry handles objects, and a Value Registry handles values. Clients of an Object Registry have to be aware of possible side-effects, while clients of a Value Registry do not have to do so.

D.14 Observer

The Observer pattern decouples a set of Observers from a Subject. It is used to maintain state dependencies between the Observers and their Subject. In case of a state change, the Subject sends out an event to notify its Observers about the change. The Subject does not rely on any specific type of Observer, but uses a common and minimal Observer protocol only. A Client configures the Subject with its Observers (Client and Observer object may well be the same).

Figure D-14: Role model of the Observer pattern.

In Java, the Observer pattern takes on the form of EventListeners.

A class-based description of this pattern can be found in [GHJV95].

D.15 Product Trader

The Product Trader pattern separates the creation of a Product object from the Client requesting it by putting the creation process into a Trader object. Clients request new Products from the Trader using a specification of the Product (rather than naming its class). The Trader uses the specification to select an element from a set of Elements. Each of the Elements can act as a Creator for the Product.

When asked for a Product, the Trader selects an Element based on the specification provided by the Client. The Trader then acts as a Client of the Element that acts as the Creator for the new Product object. The Trader/Client object asks the Element/Creator object for a new Product, which is then returned to the Client.

Figure D-15: Role model of the Product Trader pattern.

In [BR98], Bäumer and Riehle present a class-based description of this pattern.

D.16 Property List

The Property List pattern makes a Provider object provide a generic and extensible set of Properties to Clients. A Client asks a Provider object about its Properties. Properties are accessed using a naming scheme, for example simple strings, and generic get and set operations rather than through property-specific operations. The Provider defines which Properties it offers. Every implementation of a Provider may provide its own set of Properties. Properties may even be added and removed at runtime.

Figure D-16: Role model of the Property List pattern.

In [Rie97a], Riehle describes the pattern in more detail using role modeling.

D.17 Prototype

The Prototype pattern lets Clients create complex Product objects by cloning a Prototype object. Products are copies of the Prototype and reflect its possibly complex object configuration. Clients request a copy of the Prototype, which they receive as a new Product object. Prototypes serve as representatives of one or several complex objects and can be handled generically.

Figure D-17: Role model of the Prototype pattern.

A class-based description of this pattern can be found in [GHJV95].

D.18 Role Object

The Role Object pattern transparently attaches Role objects to a Core object. The Core represents an important domain concept, and the Roles represent some domain-specific extension of the Core concept. Clients make use both of the Roles and the Core. The Core manages its Roles and provides them to a Client upon request. Roles may be retrieved from the Core using a simple naming scheme, for example strings.

Figure D-18: Role model of the Role Object pattern.

The Core may be configured with Role objects in many different ways, for example during configuration time from configuration data or during execution time through dedicated clients.

In [BRSW00], Bäumer et al. present a class-based description of this pattern.

D.19 Type Object

The Type Object pattern centralizes common information about a set of Instance objects in a Type Object that is shared by all Instances. Clients ask the Type Object of an Instance for information about the Instance. This information may also be directly provided by an Instance, but it will be implemented then by asking the Type Object. Using Type Objects, otherwise redundant information about common properties of all Instances is provided in a single place, the Type Object.

Figure D-19: Role model of the Type Object pattern.

Type Object is one of the pattern triple Metaobject, Type Object, and Class Object. The distinction between Class Object and Type Object is done pragmatically. Class Objects provide implementation information about its Instances and they can manipulate and create Instances. Type Objects provide application domain specific information rather than implementation information; their implementations may be heterogeneous, and they cannot manipulate their Instances.

In [JW98], Johnson and Woolf present a class-based description of this pattern.

D.20 Serializer

The Serializer pattern reads Readable objects from a Reader and writes Writable objects to a Writer. The Reader reads the object information from a specific backend, and the Writer writes the object information to a specific backend. Backends vary with Reader/Writer implementations. The Serializer pattern is used to serialize objects for different purposes like making them persistent, marshalling and unmarshalling them, and debugging them.

Readable and Reader as well as Writable and Writer objects collaborate recursively. A Readable reads all of its attributes from a Reader. For attributes that are Readable object references, the Reader to creates the Readable and then tells it to read its attributes from it, the Reader. Similarly, a Writable writes its attributes to a Writer that in turn tells a Writable attribute to write its attributs on it, the Writer. Primitive value types like integer and string attributes end the recursive descent.

Figure D-20: Role model of the Serializer pattern.

The Serializer pattern can be viewed as the repeated specialized composition of the Visitor pattern.

In [RSB+98], Riehle et al. present a class-based description of this pattern.

D.21 Singleton

The Singleton pattern serves to ensure that there is exactly one instance of an object, the Singleton, in a given operation context, and to provide a central convenient access point to it. Historically, the operation context is the process, but it could be a thread as well. A Client requests the Singleton from a Provider. If necessary, the Provider creates the Singleton on demand.

Figure D-21: Role model of the Singleton pattern.

Because the combination of an applied Singleton role model with an object creation role model of Client, Creator, and Product role types ocurrs frequently, the dissertation uses a shortcut for it.

Figure D-22: Shortcut role model of the Singleton pattern.

A class-based description of this pattern can be found in [GHJV95].

D.22 Specification

The Specification pattern provides descriptive elements about an object to a client for use in object selection based on specifications. A Client requests a Specification from a Provider. The Specification describes one or several properties of the Provider. Typically, the Specification can provide a unique key to a client that is computed based on the properties described by the Specification and that distinguishes the Specification from Specifications of other Providers.

Figure D-23: Role model of the Specification pattern.

In [Rie96c], Riehle describes the use of the Specification pattern in the context of class selection and object creation (also known as trading), and in [EF97], Evans and Fowler describe several patterns that show how to define and compose complex specifications.

D.23 State

The State pattern serves to split a large state space of an object into several distinct parts to ease the object's implementation, to manage the state space more easily, and to extend it more easily. An Object providing domain functionality to a Client acts as the Context for a set of State objects. The Context forwards Client requests to one State object, which implements the requested behavior.

At any given time, exactly one State object is active, representing the subspace of the overall state space of the object the current state vector is in. If state changing operations cause the state vector to leave the current subspace, another State object becomes active, representing the correct subspace. A State object implements the behavior according to the rules of the subspace it represents.

Figure D-24: Role model of the State pattern.

A class-based description of this pattern can be found in [GHJV95].

D.24 Strategy

The Strategy pattern serves to configure a domain object with an instance from a family of algorithms, rather than hard-coding any specific algorithm in the domain object. The Strategy object encapsulates the algorithm, and is set to its Context by a Client. Whenever the domain object has to execute the algorithm it acts as the Context of the Strategy and delegates the task of performing the algorithm to it.

Figure D-25: Role model of the Strategy pattern.

A class-based description of this pattern can be found in [GHJV95].

D.25 Visitor

The Visitor pattern serves to extend an existing object structure with new external algorithms. The different object types from the structure are represented as different Node role types. Common to all objects is the Element role type. A Visitor object represents a new external algorithm. For each of its Node type attributes, the Element dispatches on a Visitor for the particular Node type. The Visitor can then execute the behavior associated with that particular Node type.

Because Node objects can always act as Elements, a Visitor may recursively descent into the object structure (if it is a hierarchy). An Element dispatches on an a Visitor for a given Node type attribute, and the Visitor calls on the Node type attribute to dispatch back to the Visitor on the Node type's attributes. Primitive value types and objects that are not Elements end the recursive descent.

Figure D-26: Role model of the Visitor pattern.

A class-based description of this pattern can be found in [GHJV95].

Copyright (©) 2007 Dirk Riehle. Some rights reserved. (Creative Commons License BY-NC-SA.) Original Web Location: http://www.riehle.org