Using Design Patterns in UML
Many a time when you design or implement solutions for a software system, you get the feeling of dij` vu. Even though this may sound too extreme, it is undeniable that parts of different software systems may share similar aspects. With software design going the assembly line way, reusability has become an important criterion in software design
A pattern is a commonly occurring reusable piece in software system that provides a certain set of functionality. The identification of a pattern is also based on the context in which it is used. So, using patterns in modeling of systems helps in keeping design standardized and more importantly, minimizes the reinventing of the wheel in the system design. This article is all about patterns; especially design patterns.
Ok so you might ask how does a pattern relate to the UML? The patterns that we encounter need to be captured and documented in a sufficiently descriptive manner so that they can be referred for future use. UML provides the perfect tools to do just this. The class diagram in UML can be used to capture the patterns identified in a system. In addition, UML has a sufficiently extensive and expressive vocabulary to capture the details of patterns.
Over the previous articles in this series, we explored the different UML diagrams and learned how to model each of the diagrams in a case study application. Building on this background we will see how to leverage the usefulness of well-known patterns to make application designing a lot easier.
To sum up, a pattern should have the following characteristics
- Useful solution
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides first popularized the concept of patterns with their book on design patterns. These authors came to be known as the "Gang Of Four" or GOF. The name stuck ever since and the patterns catalog that they documented is known as the GOF patterns catalog.
Since a system is made up of static as well as dynamic elements, you will find patterns that can be used for either of these types. For static elements of a system especially the architecture and design of a system, there are design patterns - the focus of this article. The dynamic aspects of a system are abstracted and captured as process patterns. But patterns are not limited to this. Patterns can be abstracted for the implementation aspects of a system as well.
Based on how they are to be used, patterns are primarily categorized as:
Creational patterns define mechanisms for instantiating objects. The implementation of the creational pattern is responsible for managing the lifecycle of the instantiated object. A few examples of Creational design patterns are listed below.
One of the easily recognized and frequently used design patterns is the Factory pattern. If you have designed any object that is responsible for creating and maintaining the lifecycle of another object, you have used the Factory pattern. Obtaining a database connection in your application using a connection manager or connection factory object is a good example of the Factory pattern.
Figure 1. Factory pattern
A singleton is another example of a factory pattern. What makes the Singleton pattern unique is that one and only one instance of the object can exist irrespective of the number of times the object is instantiated. The most common use of a Singleton pattern is for server applications like a Java based Remote Method Invocation (RMI) server application.
Figure 2. Singleton pattern
The composition of objects and their organization to obtain new and varied functionality is the underlying basis of Structural patterns. A few examples of Structural design patterns are listed below.
In the Adapter pattern, an object provides an implementation of an interface used by other objects in a consistent way. The adapter object wraps different disparate implementations of the interface and presents a unified interface for other objects to access. A good example of this is a database driver like an ODBC (Open Database Connectivity) or JDBC (Java Database Connectivity) driver that wraps the custom database accessing implementation for different databases and yet, presents a consistent interface that is a published and standardized API.
Figure 3. Adapter pattern
A Proxy pattern constitutes use of proxy objects during object interaction. A proxy object acts as a substitute for the actual object. Use of proxy objects is prevalent in remote object interaction protocols. As an example, when an object needs to interact with a remote object, say across a network, the most preferred way of encapsulating and hiding the interaction mechanism is by using a proxy object that mediates communication between the requesting object and the remote object.
Figure 4. Proxy pattern
Interaction between different objects is specifically covered by Behavioral patterns. Some examples of behavioral patterns are given below.
The Command pattern is commonly used for gathering requests from client objects and packaging them into a single object for processing. The Command pattern allows for having well defined command interfaces that are implemented by the object that provides the processing for the client requests packaged as commands.
Figure 5. Command pattern
A simple mechanism to traverse and access a list of objects is defined by the Iterator pattern. The Iterator pattern encapsulates the internal implementation of the list while providing a standardized mechanism for list traversal.
Figure 6. Iterator pattern