Factory design pattern
implements the concept of real world factories. Factory pattern is a creational
design pattern. It deals with creating object without specifying exact class.
In general, actors of factory patterns are a client, a factory and a product.
Client is an object that requires another object for some purposes. Rather than
creating the product instance directly, the client delegates this
responsibility to the factory. The factory then creates a new instance of the
product, passing it back to the client. Figure shows the whole process.
Application
For an example, a banking
application works with accounts. In this application there are different types
of account like saving account and checking account. All accounts are derived
from an abstract account name IAccount. The IAccount defines the withdraw,
deposit and interest rate which must be implemented by the concrete accounts (saving
account, checking account). If clients want to know the interest rate of the
Saving Account. It just invoke the factory to create an instance of Saving
account. Being invoked factory, it
creates an instance of the saving account and then client just get the interest
rate by invoking interest method. The client uses the object as casted to the abstract
class without being aware of the concrete object type. Over all implementation
of this scenario is given below.
The advantage is in here that
new account can be added without changing a single line of code in the client
code. Here an object is created without exposing instantiation logic to the
client. The object generation is centralized here.
Benefits:
- Factory Pattern is the mostly used pattern.
- Decoupled the classes i.e eliminates the need to bind application specific class
- The code only deals with the Interface.
- Factory Pattern provides the way to create multiple instances of classes.
- This provides a hook so that we can derive a sub-class to create different controls to display the data.
- Factory method connects the class hierarchies with minimum coupling.
- Product implementation may change over time but client remains unchanged.
Implementation
Step 1: Create an Interface - IAccount
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { public interface IAccount { string Withdraw(int amount); string Deposit(int amount); double InterestRate(); } }
Step 2: Create concrete classes
Saving account
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { ////// Concrete class SavingsAccount /// public class SavingsAccount : IAccount { #region IAccount Members public string Withdraw(int amount) { throw new NotImplementedException(); } public string Deposit(int amount) { throw new NotImplementedException(); } public double InterestRate() { return 12.5; } #endregion } }
Checking Account
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { ////// Concrete class CheckingAccount /// public class CheckingAccount : IAccount { #region IAccount Members public string Withdraw(int amount) { throw new NotImplementedException(); } public string Deposit(int amount) { throw new NotImplementedException(); } public double InterestRate() { return 10.24; } #endregion } }
Step 3: Create a
Factory Object Enum
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { ////// FactoryObject Enum to configure object /// public enum FactoryObject { SavingAccount, CheckingAccount } }
Step
4: Create a factory class
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { ////// Factory class to create object /// public static class Factory { public static IAccount CreateObject(FactoryObject factoryObject) { IAccount objIAccount = null; switch (factoryObject) { case FactoryObject.SavingAccount: objIAccount = new SavingsAccount(); break; case FactoryObject.CheckingAccount: objIAccount = new CheckingAccount(); break; default: break; } return objIAccount; } } }
Step
5: Access from client
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FactoryPattern { public class Program { public static void Main(string[] args) { //Create object by factory pattern IAccount objSavingAccount = Factory.CreateObject(FactoryObject.SavingAccount); IAccount objCheckingAccount = Factory.CreateObject(FactoryObject.CheckingAccount); //Access object Console.WriteLine("Saving Account Interest Rate: " + objSavingAccount.InterestRate()); Console.WriteLine("Checking Account Interest Rate: " + objCheckingAccount.InterestRate()); Console.ReadLine(); } } }