Search This Blog

2009-11-09

Design Patterns Overview

Software professionals may be familiar with the term "Design Patterns," but many have no idea of where they come from and what they truly are. Consequently, some do not see the value and benefits design patterns bring to the software development process, especially in the areas of maintenance and code reuse. This article will bridge this gap by defining design patterns from a historical perspective.

What is design Patterns:
A design pattern can solve many problems by providing a framework for building an application. Design patterns, which make the design process cleaner and more efficient, are especially well-suited for use in C# development because it is an object-oriented language. So design patterns are recurring solutions to software design problems you find again and again in real-world application development.

Benefits of Design Patterns
Design patterns have two major benefits. First, they provide you with a way to solve issues related to software development using a proven solution. The solution facilitates the development of highly cohesive modules with minimal coupling. They isolate the variability that may exist in the system requirements, making the overall system easier to understand and maintain. Second, design patterns make communication between designers more efficient. Software professionals can immediately picture the high-level design in their heads when they refer the name of the pattern used to solve a particular issue when discussing system design.

Core Categories Of DP
-Creational
-Structural
-Behavioral

Just for info ,other than the main core category we have many design patterns like Concurrency pattern,Process pattern

Creational Design Patterns: The patterns in this category deal with object creation mechanisms by trying to create objects in a manner suitable to the situation.
For example, you want to create an object creation delayed at runtime instead of compile time, or you want a system to have only one object can exist of a class.
Creational Patterns
√ Abstract Factory:- Creates an instance of several families of classes
√ Builder :- Separates object construction from its representation
√ Factory Method:- Creates an instance of several derived classes
√ Prototype:- A fully initialized instance to be copied or cloned
√ Singleton:- A class in which only a single instance can exist

Structural Design patterns: The pattern in this category provide solutions to the problems dealing with the composition of objects
For example, Assume you want to bring different incompatible interface together or want to bring unified interface together
Structural Patterns
√ Adapter:-Match interfaces of different classes.
√ Bridge:-Separates an object’s interface from its implementation.
√ Composite:-A tree structure of simple and composite objects.
√ Decorator :-Add responsibilities to objects dynamically.
√ Façade:-A single class that represents an entire subsystem.
√ Flyweight:-A fine-grained instance used for efficient sharing.
√ Proxy:-An object representing another object.


Behavioral Patterns: The pattern in this category provide solutions to the problems dealing with the way object interact with each other. These patterns help to increase the flexibility in establishing the communication among various system objects.
Example ,you want to change an object behavior when its internal state changes.
Behavioral Patterns
√ Mediator:-Defines simplified communication between classes.
√ Memento:-Capture and restore an object's internal state.
√ Interpreter:-A way to include language elements in a program.
√ Iterator:-Sequentially access the elements of a collection.
√ Chain of Resp:-A way of passing a request between a chain of objects.
√ Command:-Encapsulate a command request as an object.
√ State:-Alter an object's behavior when its state changes.
√ Strategy:-Encapsulates an algorithm inside a class.
√ Observer:-A way of notifying change to a number of classes.
√ Template Method:-Defer the exact steps of an algorithm to a subclass.
√ Visitor:-Defines a new operation to a class without change.

Before starting the UML Diagram of a design pattern,I would like to explain a simple class diagram to understand the different UML notation and relationship.

First observe the diagram


UML class notation is a rectangle divided into three parts: class name, attributes, and operations. Names of abstract classes, such as Payment, are in italics. Relationships between classes are the connecting links.
Our class diagram has three kinds of relationships.
a)association -- a relationship between instances of the two classes. There is an association between two classes if an instance of one class must know about the other in order to perform its work. In a diagram, an association is a link connecting two classes.
b)aggregation -- an aggregation in which one class belongs to a collection. An aggregation has a diamond end pointing to the part containing the whole. In our diagram, Order has a collection of OrderDetails.
c)generalization -- an inheritance link indicating one class is a superclass of the other. A generalization has a triangle pointing to the superclass. Payment is a superclass of Cash, Check, and Credit.
An association has two ends. An end may have a role name to clarify the nature of the association. For example, an OrderDetail is a line item of each Order.
A navigability arrow on an association shows which direction the association can be traversed or queried. An OrderDetail can be queried about its Item, but not the other way around. The arrow also lets you know who "owns" the association's implementation; in this case, OrderDetail has an Item. Associations with no navigability arrows are bi-directional.
The multiplicity of an association end is the number of possible instances of the class associated with a single instance of the other end. Multiplicities are single numbers or ranges of numbers. In our example, there can be only one Customer for each Order, but a Customer can have any number of Orders.

This table gives the most common multiplicities.

0..1 =zero or one instance. The notation n . . m indicates n to m instances.
0..* or * =no limit on the number of instances (including none).
1 =exactly one instance
1..*= at least one instance

Every class diagram has classes, associations, and multiplicities. Navigability and roles are optional.



Lets firts describe a Factory Pattern.

Factory Pattern
Its Creates an instance of several derived classes.
“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.” -- "Design Patterns” Gamma et al., Addison-Wesley, ISBN:0-201-63361-2”



The following is an UML representation of the Factory Method Pattern. In this case we are not directly creating an instance of the class Derived1 and Derived2. Instead we are using the getObject() method of the Factory class to return an appropriate instance depending on the value passed to the getObject() method. This method is commonly knows as the Factory method and Factory method can be either static or non-static in nature.





In Factory method pattern, A Factory class contains a factory method is used for creating the object. This factory method can be either static or non-static.
Client class needn’t know about instance creation.

Abstract Factory:It "Provide an interface for creating families of related or dependent objects without specifying their concrete classes" -- "Design Patterns" Gamma et al., Addison-Wesley, ISBN:0-201-63361-2"


Builder Pattern:Builder is an object creational design pattern that codifies the construction process outside of the actual steps that carries out the construction - thus allowing the construction process itself to be reused.





Singleton pattern:A class in which only a single instance can exist.
The purpose of a singleton pattern is to ensure a unique instance of the class and to provide global access to this.
It maintain the unique instance throughout the life of the program(s) in which this class is created.
The logic of the CreateInstance method is pretty straightforward. Check, if any instance has already been created, if yes, return the instance, else create and store the instance and return it. It is obvious here again, storing the instance has to be done in a private static variable, static because, you are doing this in a static method, private because, you need to do the maintenance of the singleton instance creation.




Adapter Class:During object-oriented developments, some times we have to use an unrelated class along with our existing class hierarchy. The simplest solution is to make a wrapper or adaptor around the foreign class, which is acceptable by the existing class hierarchy. This is what known as the ADAPTOR PATTERN or WRAPPER PATTERN.
Lets take a non-software Example
Socket wrenches provide an example of the Adapter. A socket attaches to a ratchet, provided that the size of the drive is the same. Typical drive sizes in the United States are 1/2" and 1/4". Obviously, a 1/2" drive ratchet will not fit into a 1/4" drive socket unless an adapter is used. A 1/2" to 1/4" adapter has a 1/2" female connection to fit on the 1/2" drive ratchet, and a 1/4" male connection to fit in the 1/4" drive socket. [Michael Duell, "Non-software examples of software design patterns", Object Magazine, Jul 97, p54]

Let us see the following class hierarchy.

How we can fit a foreign class or interface say ADAPTEE to this class hierarchy. It is possible by introducing an ADAPTOR class as shown below.

In the above case the ADAPTOR class inherits from both BASE CLASS & ADAPTEE class. This type of mechanism based on the multiple inheritances is known as class adaptors. Remember that this may be introducing the violation of Open Closed Principle (OCP) or Lisknov's Substitution Principle (LSP). But if we are using class adaptors, better to use a private inheritance with respect to the ADAPTEE class.

The Open Closed Principle states that classes should be open for extension but closed for modification. Or to say it another way, it should be possible to add new features and capabilities to your codebase simply by creating new classes, rather than having to mess with the internals of existing classes.

Likov's Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.

Instead of inheriting from the ADAPTEE class, the ADAPTOR class can contain an instance of ADAPTEE class and use that instance. This mechanism employs the object adaptors. The UML representation of Object adaptor is shown below.



In class adaptor, it is possible to override some of the behaviors of the ADAPTEE class in ADAPTOR class. But class adaptor will not work when we want to adapt ADAPTEE class and all its derived classes.

But an object adaptor can work with the ADAPTEE class and all its subclasses.

No comments: