When experts need to solve a problem, they seldom invent a totally new solution. More often they will recall a similar problem they have solved previously and reuse the essential aspects of the old solution to solve the new problem. They tend to think in problem-solution pairs.
Identifying the essential aspects of specific problem-solution pairs leads to descriptions of problem-solving patterns that can be reused.
The concept of a pattern as used in software architecture is borrowed from the field of (building) architecture, in particular from the writings of architect Christopher Alexander.
Where software architecture is concerned, the concept of a pattern described here is essentially the same concept as an architectural style or architectural idiom in the Shaw and Garlan textbook.
In general, patterns have the following characteristics [Buschmann]:
Various authors use different formats (i.e., "languages") for describing patterns. Typically a pattern will be described with a schema that includes at least the following three parts [Buschmann]:
The Context section describes the situation in which the design problem arises.
The Problem section describes the problem that arises repeatedly in the context.
In particular, the description describes the set of forces repeatedly arising in the context. A force is some aspect of the problem that must be considered when attempting a solution. Example types of forces include:
Forces may complementary (i.e., can be achieved simultaneously) or contradictory (i.e., can only be balanced).
The Solution section describes a proven solution to the problem.
The solution specifies a configuration of elements to balance the forces associated with the problem.
Patterns can be grouped into three categories according to their level of abstraction [Buschmann]:
Shaw and Garlan normally use the term architectural style for the architectural pattern concept described here.
An architectural pattern is a high-level abstraction. The choice of the architectural pattern to be used is a fundamental design decision in the development of a software system. It determines the system-wide structure and constrains the design choices available for the various subsystems. It is, in general, independent of the implementation language to be used.
An example of an architectural pattern is the pipes and filters pattern we will examine later. In Unix for instance, a filter is a program that reads a stream of bytes from its standard input and writes a transformed stream to its standard output. These programs can be chained together with the output of one filter becoming the input of the next filter in the sequence via the pipe mechanism. Larger systems can thus be constructed from simple components that otherwise operate independently of one another.
Other example architectural patterns are layered systems, blackboards, and the model-view-controller pattern for graphical user interfaces.
A design pattern is a mid-level abstraction. The choice of a design pattern does not affect the fundamental structure of the software system, but it does affect the structure of a subsystem. Like the architectural pattern, the design pattern tends to be independent of the implementation language to be used.
An example of a design pattern is the Adaptor (or Wrapper) design pattern. This pattern adapts the interface of one existing type of object to have the same interface as a different existing type of object. For instance, in the second transformation in the paper "Creating Applications from Components: A Manufacturing Framework Design" by H. A. Schmid (IEEE Software, Nov. 1996), we saw that a portal robot machine class can be adapted for use as a transport service class.
Another example design pattern is the Strategy (or Policy) pattern.
The goal of this pattern is to allow any one of a family of related
algorithms to be easily substituted in a system. We also saw this
pattern in the Schmid article; the third transformation involved
breaking up the application logic class ProcessingControl
into several subclasses of a new ProcessingStrategy
class. The specific processing strategy could then be selected
dynamically based on the specific part-processing task.
An idiom is a low-level abstraction. It is usually a language-specific pattern that deals with some aspects of both design and implementation.
An example of an idiom is the use of iterators to step through
container data structures. For instance, a Java object that
implements the Enumeration
interface is returned by the
elements()
of a Vector
object; successive
calls of the nextElement()
method of the
Enumeration
object returns successive elements of the
Vector
object.
(Note: In the Java Development Kit 1.2 and beyond, class
Vector
has been retrofitted to be a part of the new
Collection
hierarchy, which has a safer new iterator
mechanism defined by the Iterator
interface.)
Another example of an idiom is the use of the Counted Body (or Reference Counting) technique for storage management in C++.
UP to ENGR 691 Lecture Notes root document?