Design Patterns

Patterns in the usage of classes and therir relationships occur many times in program designs. The pattersn have been abstracted and can be reused in a new design as long as the pattern can be recognized as appropriate.

Patterns are suggested solutions to general problems, not specific solutions to specific problems. The must be adapted to be used at all. Rarely can they be used unaltered.

Good patterns are as general as possible and be easy to understand. It should also have a name that is easy to remember. Most patterns can be represented using a UML class diagram. The "forces" that drive a pattern are the set of issues that the pattern addresses, its level of generality, and, ultimately, its usefulness. There are many pattern catalogs with many different patterns. What you use is a judgement call depending on the structure of your system (the problem) and its design (the solution).

Patterns embody not only the basic OO principles (abstraction, encapsulation, inheritance and polymorphism) but also design principles:

  • identify aspects that vary, and separate them from what remaians the same - encapsulate what varies
  • favor composition over inheritance
  • program to interfaces, not implementations
  • strive for loosely coupled designs between objects that interact
  • reduce the number of dependencies between classes
  • classes should be open for extension, but closed for modification
  • depend on abstractions, not concrete classes
  • have superclasses call subclasses when needed
  • a class should have only one responsibility

Common patterns and their class diagrams are:

Strategy: defines a family of algorithms, encapsulates each one and makes them interchangeable.

Sample files for a mini simulation of duck behavior. (strategy.jude)

Observer: a one-to-many dependency between objects so that when one object changes state, all the dependent objects are notified and updated automatically

Sample files for a weather station. (observer.jude)

Decorator: Attach additonal responsibilities to an object dynamically.

Sample files for a coffee shop. (decorator.jude)

Factory: defines an interface for creating objects, but lets subclasses decide which class to instantiate

Sample files for a pizza store. (factory.jude)

Abstract factory: provides an interface for creating families of relalted or dependent objects without specifying their concrete classes.

Sample files for a pizza store with ingredient factories. (abstractfactory.jude)

Singleton: ensures that a class has only one instance, an provides a global point of access to it.

Sample file for a company. (singleton.jude)

Command: encapsulates a request as an object, thereby letting you parameterize othe objects with different requests, and to support undoable operations.

Sample files for a home automation system. (command.jude)

Adapter: converts the interface of a class into another interface the client expects.

Sample files for a turkey masquerading as a duck. (adapter.jude)

Facade: provides a unified interface to a set of interfaces in a subsystem.

Sample files for a home automation system. (facade.jude)

Template: defines the skeleton of an algorithm in a method, deferring some steps to subclasses.

(template.jude)

Iterator/composite: allows traversal of the elemetns of an aggregate without exposing the underlying implementation.

Sample files for the menus at a diner. (iterator.jude)

State: allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

Sample files for a gumball machine. (state.jude)

Proxy: provides a surrogate or placeholder for another object to control access to it.

Sample files for a remote gumball machine monitor. (proxy.jude)