This is the third in a series of blog posts, we are doing on Building Enterprise Framework for .NET based Web Application.
Our first three iteration of framework was not using any design patterns, modules were dependent on each other and it was very hard to update any module without breaking any dependent module. I don’t know what everyone else’s experience is, but finding developers who are familiar with Design Patterns has been extremely rare for me. Personally, I think design patterns should be a basic skill for all developers.
The idea of Design Pattern came from a book “A Pattern Language: Towns, Buildings, Construction” in 1977 co-authored by Christopher Alexander as “a structured method of describing good design practices within a field of expertise.” The book creates a new language, what the authors call a pattern language derived from timeless entities called patterns. Patterns describe a problem and then offer a solution. The idea of a pattern language appears to apply to any complex engineering task, and has been applied to some of them. It has been especially influential in software engineering where patterns have been used to document collective knowledge in the field.
Design patterns are optimized, reusable solutions to the programming problems that we encounter every day. You can’t simply copy a pattern into a system, because it is just a template you have to implement in correct situation. Design patterns can be extremely helpful in writing better code, but the way in which they’re applied often determines their usefulness. Applying a design pattern in the wrong scenario can leads you to write worse code than would have not been present if it weren’t for the design pattern.
We are not going to discuss all design patterns here but the more popular ones, but you can refer these books for more information:
- Design Patterns: Elements of Reusable Object-Oriented Software
- Head First Design Patterns
- Patterns of Enterprise Application Architecture
Factory Method Pattern
The factory method pattern is an object-oriented creational design pattern to implement the concept of factories and deals with the problem of creating objects (products) without specifying the exact class of object that will be created. The essence of this pattern is to “Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
The participants classes in this pattern are:
- Product defines the interface for objects the factory method creates.
- ConcreteProduct implements the Product interface.
- Creator(also referred as Factory because it creates the Product objects) declares the method factoryMethod, which returns a Product object. May call the generating method for creating Product objects
- ConcreteCreator overrides the generating method for creating ConcreteProduct objects
All concrete products are subclasses of the Product class, so all of them have the same basic implementation, at some extent. The Creator class specifies all standard and generic behavior of the products and when a new product is needed, it sends the creation details that are supplied by the client to the ConcreteCreator.
When to use Factory Method Pattern:
- When a class can’t anticipate the type of the objects it is supposed to create.
- When a class wants its subclasses to be the ones to specific the type of a newly created object.
The singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.
Implementation of a singleton pattern requires a mechanism to access the singleton class member without creating a class object and a mechanism to persist the value of class members among class objects. The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object. To make sure that the object cannot be instantiated any other way, the constructor is made private.
When to use Singleton Pattern:
- Ensure that only one instance of a class is created.
- Provide a global point of access to the object.
The builder pattern is a design pattern that separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations.
The participants classes in this pattern are:
- The Builder class specifies an abstract interface for creating parts of a Product object.
- The ConcreteBuilder constructs and puts together parts of the product by implementing the Builder interface. It defines and keeps track of the representation it creates and provides an interface for saving the product.
- The Director class constructs the complex object using the Builder interface.
- The Product represents the complex object that is being built.
The client, that may be either another object or the actual client that calls the main() method of the application, initiates the Builder and Director class. The Builder represents the complex object that needs to be built in terms of simpler objects and types. The constructor in the Director class receives a Builder object as a parameter from the Client and is responsible for calling the appropriate methods of the Builder class. In order to provide the Client with an interface for all concrete Builders, the Builder class should be an abstract one. This way you can add new types of complex objects by only defining the structure and reusing the logic for the actual construction process. The Client is the only one that needs to know about the new types, the Director needing to know which methods of the Builder to call.
When to use Builder Pattern:
- The creation algorithm of a complex object is independent from the parts that actually compose the object.
- The system needs to allow different representations for the objects that are being built.
The Provider Design Pattern is a pattern which was introduced in ASP.NET 2.0. The theory of the pattern is that it allows us to define a well-documented, easy-to-understand API, such as ASP.NET 2.0 Membership APIs, but at the same time give developers complete control over the internals of what occurs when those APIs are called.
A provider is a contract between an API and the Business Logic and/or the Data Abstraction Layer. The provider is the real implementation of the API separate from the API itself. So the API itself does not contain any business logic, instead it forwards a call to the configured provider for it. The provider is responsible for the implementation of the API (or a part of it) and can call whatever type of BLL or DAL.
When to use Provider Pattern:
- When you need to design evolving decoupled API interfaces and their implementations.
The repository pattern is a design pattern that separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model.
The repository mediates between the data source layer and the business layers of the application. It encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
When to use Repository Pattern:
- When you need to centralizes the data logic or Web service access logic.
- When you need to provides a substitution point for the unit tests.
- When you need to provides a flexible architecture that can be adapted as the overall design of the application evolves.
Unit of Work
The Unit of Work pattern is a design pattern that maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
When you’re pulling data in and out of a database, it’s important to keep track of what you’ve changed; otherwise, that data won’t be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.
You can change the database with each change to your object model, but this can lead to lots of very small database calls, which ends up being very slow. Furthermore it requires you to have a transaction open for the whole interaction, which is impractical if you have a business transaction that spans multiple requests. The situation is even worse if you need to keep track of the objects you’ve read so you can avoid inconsistent reads.
When to use Unit of Work Pattern:
- When you need to manage transactions.
- When you need to execute the database inserts, deletes, and updates.
- When you need to prevent duplicate updates.
Dependency injection is a design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time.
You have classes that have dependencies on services or components whose concrete type is specified at design time. In this example, ClassA has dependencies on ServiceA and ServiceB.
This situation has the following constraints:
- To replace or update the dependencies, you must change your classes source code.
- The concrete implementation of the dependencies must be available at compile time.
- Your classes are difficult to test in isolation because they have a direct reference to their dependencies. This means that these dependencies cannot be replaced with stubs or mocks.
- Your classes contain repetitive code for creating, locating, and managing their dependencies.
With Dependency injection, We don’t instantiate dependencies explicitly in the class. Instead, we declaratively express dependencies in class definition. We use a Builder object to obtain valid instances of object’s dependencies and pass them to object during the object’s creation and/or initialization.
When to use Dependency Injection
- You want to decouple your classes from their dependencies so that these dependencies can be replaced or updated with minimal or no changes to your classes’ source code.
- You want to be able to write classes that depend on classes whose concrete implementation is not known at compile time.
- You want to be able to test your classes in isolation, without using the dependencies.
- You want to decouple your classes from being responsible for locating and managing the lifetime of dependencies.
Don’t forget to tell us what design patterns you use while developing web application. Please leave your comments, feedback and suggestions in the comments section below.