Software design is something of a black art. The techniques used by master designers could only be learned by experience over a long period of time. While general design principles such as coupling and cohesion are well known, such concepts are sufficiently general and amorphous that they provide little direct help in learning to design well, thus the need for on-the-job training. Design patterns are a relatively recent advancement in software engineering that facilitate the transfer of design knowledge between expert and novice. In software design the same problems and situations tend to occur over and over again. Such recurring problems are amenable to standard solutions that can be reused whenever the problem reappears. A design pattern captures the solution to a specific design problem, thus allowing one to learn the solution before actually encountering the problem through direct experience. Design patterns also provide examples of high-quality designs. One of the best ways to learn to design better is to see good examples that help you gain a sense of how to distinguish between good and bad designs. (i.e., If you've never seen a good design, how an you be expected to create one yourself?) Design patterns all follow the same general format: 0) Name 1) Problem - a description of the specific design problem the pattern solves 2) Solution - a description of how the design problem is solved 3) Consequences - the consequences of using the pattern (some good, some bad) 4) Implementation - issues that arise when implementing the pattern 5) Known Uses - example applications of the pattern Different Levels of Patterns 1) Architecture Patterns - provide structure for an entire system 2) Design Patterns - subsystem-level patterns (several classes working together) 3) Idioms - Low-level, language-specific implementation techniques (e.g., Resource acquisition is initialization (C++), Smart pointers (C++), etc.)