Sei sulla pagina 1di 8

Understanding and Implementing Factory

Pattern in C#
Rahul Rajat Singh, 9 Feb 2015

Introduction
In this article we will try to understand what is Factory Pattern, what are the benefits of this pattern
and how can we implement this pattern using C#.

Background
It is almost impossible to have an application that contains only one class. Typically an application
will have many classes involved, each with a dedicated responsibility, to implement the desired
functionality. Which would mean that it is inevitable for the classes to communicate with other
classes. This can easily be achieved if we let the classes instantiate the classes it needs and the call
the methods on these classes.

So if we have a class A that want to call a method of class B, we can simply have an object
of B inside A and call its methods whenever we need to. The code will look something like
following.

Hide Copy Code

public class B
{
public void DoTaskOne()
{
Console.WriteLine("B.DoSomething");
}
}

public class A
{
private B b;

public A()
{
b = new B();
}

public void GetOneDone()


{
b.DoTaskOne();
}
}
This approach of having the class instances contained inside other classes will work but it has some
downsides. The first problem is that each class needs to know about every other class that it wants to
use. This will make this application a maintenence nightmare. Also, the above approach will increase
the coupling between the classes.

From the best practices' perspective whenever we are designing our classes we should keep the
dependency inversion principle in mind when it comes to dependency between classes. Dependency
Inversion Principle says that the higher level modules should always depend on abstractions rather
than lower level modules directly. So we should always design our classes in such a way that they
always depend on the interfaces or abstract classes rather than other concrete classes.

So the classes we saw in the above example will change. We first need to have an interface
that A can use to call DoTaskOne. Class B should implement this interface. The new classes will look
like following.

Hide Shrink Copy Code

interface IDoable
{
void DoTaskOne();
}

public class B : IDoable


{
public void DoTaskOne()
{
Console.WriteLine("B.DoSomething");
}
}

public class A
{
private IDoable doable;

public A()
{
// How to create the doable object here???
// doable = new B();
// This seems wrong
}

public void GetOneDone()


{
doable.DoTaskOne();
}
}

The above code shows the classes perfectly designed where the higher lever modules depend on
abstractions and the lower level modules implementing these abstractions. But wait... How are we
going to create and object of B. Should we still do that as we did in the previous code i.e. doing a
new on B in the A's constructor? But would it not defeat the whole purpose of having loose
coupling?
This is exactly where the Factory pattern will be useful. The Factory completely hides the process of
creating objects. Factory pattern totally abstract our the responsibility of creating classes from the
client classes. The major benefit of this is that our client code is completely ignorant of creation
process of dependent classes. So to instantiate the actual in our above code we have to do
something like the following in the constructor.

Hide Copy Code

public class DoableFactory


{
public B GetConcreteDoable()
{
return new B();
}
}

// Constructor of A
public A()
{
DoableFactory factory = new DoableFactory();
doable = factory.GetConcreteDoable();
}

This loose coupling also good from the extensibility perspective. With the factory pattern in place,
the client code also has the possibility of using multiple dependent classes as long as these
dependent classes adhere to the contract i.e. implement interface. So in the above example the client
code will simply not be calling the factory method but will also be providing some information that
can be used to identify the concrete object that needs to be created.

Using the Code


The example we saw above was rather contrived. To understand the Factory pattern, let us try to
implement a sample application. Lets say we have an eCommerce application and we have 2
payment gateways integrated with our application. Let call these payment gateways as BankOne and
BankTwo. The BankOne charges 2% on credit cards if the order is less that 50 USD and 1% if it is
more than 50 USD. BankTwo one other hand charges flat 1.5% for all the amounts.

So our payment module presents the user with three options as:

 BankOne
 BankTwo
 Best for me

Lets start by looking at our Product model. This product model will represent the product that the
user is trying to purchase.

Hide Copy Code


class Product
{
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}

Now let us look at IPaymentGateway interface first. This interface will define the contract that all
the payment gateways i.e. banks' classes should conform to.

Hide Copy Code

interface IPaymentGateway
{
void MakePayment(Product product);
}

Note: In real world the MakePayment will also accept user information to identify the user. We are
not showing it here to keep the sample free from digression.

Now lets create the classes that will contain the actual code for making the payment by invoking the
bank specific API.

Hide Copy Code

public class BankOne : IPaymentGateway


{
public void MakePayment(Product product)
{
// The bank specific API call to make the payment
Console.WriteLine("Using bank1 to pay for {0}, amount {1}", product.Name,
product.Price);
}
}

public class BankTwo : IPaymentGateway


{
public void MakePayment(Product product)
{
// The bank specific API call to make the payment
Console.WriteLine("Using bank2 to pay for {0}, amount {1}", product.Name,
product.Price);
}
}

Now its time to create our factory class to handle all the gory details of creating these objects. To be
able to identify what payment mechanism user has selected, lets define a simple
Enum PaymentMethod.

Hide Copy Code


enum PaymentMethod
{
BANK_ONE,
BANK_TWO,
BEST_FOR_ME
}

The factory class will use this enum to identify what payment gateway concrete class should be
created. Lets look at our factory class implementation now.

Hide Shrink Copy Code

public class PaymentGatewayFactory


{
public virtual IPaymentGateway CreatePaymentGateway(PaymentMethod method, Product product)
{
IPaymentGateway gateway = null;

switch(method)
{
case PaymentMethod.BANK_ONE:
gateway = new BankOne();
break;
case PaymentMethod.BANK_TWO:
gateway = new BankTwo();
break;
case PaymentMethod.BEST_FOR_ME:
if(product.Price < 50)
{
gateway = new BankTwo();
}
else
{
gateway = new BankOne();
}
break;
}

return gateway;
}
}

What our factory class is doing is that it is accepting the user selected payment gateway and then
based on the selection it is creating the concrete payment gateway class. As we can see that it has a
lot of logic to decide which payment gateway to select, we have effectively abstracted out all these
gory details from the client code. Otherwise every class that want to use a payment gateway would
have to write all this logic. Lets now look at how the client class can use this factory method to make
the payment.

Hide Copy Code

public class PaymentProcessor


{
IPaymentGateway gateway = null;
public void MakePayment(PaymentMethod method, Product product)
{
PaymentGatewayFactory factory = new PaymentGatewayFactory();
this.gateway = factory.CreatePaymentGateway(method, product);

this.gateway.MakePayment(product);
}
}

Now our client class does not depend on the concrete payment gateway classes. It also does not
have to worry about the creation logic of the concrete payment gateway classes. All this is nicely
abstracted out in the factory class itself.

The Factory pattern is a very useful pattern when it comes to keeping our client code decoupled
from dependent classes. It enables the application to be maintained more easily. It also makes it very
easy to extend as new concrete classes can be added as without impacting the existing concrete
classes and the client code.

Looking at GoF Factory Method

GoF defines factory method as “Define an interface for creating an object, but let subclasses decide
which class to instantiate. Factory Method lets a class defer instantiate to subclasses”. If we look at the
class diagram for Factory Method (Reference: GoF Design Patterns):

Lets see what each of these classes represents:

 Product: defines the interface of objects the factory method creates (IPaymentGateway)
 ConcreteProduct: implements the Product interface (BankOne, BankTwo)
 Creator: declares the factory method, which returns an object of type Product.
(PaymentGatewayFactory)
 ConcreteCreator: overrides the factory method to return an instance of a ConcreteProduct

Now if we compare our current implementation with the GoF factory method, we have our
interface IPaymentGateway which is interface of objects the factory method creates. We have
our BankOne and BankTwo classes that are the ConcreteProducts. As for the factory classes, we
are using a single factory class PaymentGatewayFactory instead of having a hierarchy. But on a
closer look we will see that our factory class is in fact the Creator class of GoF patterns. The only
difference is that instead of being a pure abstract class our class comes with some abstract behavior.

So how can we plug in and use ConcreteCreator with our design. Lets say we want to create
more concrete payment gateway classes that will be used by other parts of the application. To do
this, we first have to have new enums values for the new concrete classes like following:

Hide Copy Code

enum PaymentMethod
{
BANK_ONE,
BANK_TWO,
BEST_FOR_ME,

PAYPAL,
BILL_DESK
}

Now we can have one factory class derived from our PaymentGatewayFactory class which will
contain the logic for these new payment gateways.

Hide Copy Code

public class PaymentGatewayFactory2 : PaymentGatewayFactory


{
public virtual IPaymentGateway CreatePaymentGateway(PaymentMethod method, Product product)
{
IPaymentGateway gateway = null;

switch (method)
{
case PaymentMethod.PAYPAL:
// gateway = new PayPal();
break;
case PaymentMethod.BILL_DESK:
// gateway = new BillDesk();
break;
default:
base.CreatePaymentGateway(method, product);
break;
}

return gateway;
}
}

Now wherever we want to use the newly added payment mechanism, we just have to
create PaymentGatewayFactory2 instead of PaymentGatewayFactory and all the 5 payment
gateway concrete classes will be available to the client code.

Hide Copy Code

public class PaymentProcessor2


{
IPaymentGateway gateway = null;

public void MakePayment(PaymentMethod method, Product product)


{
PaymentGatewayFactory2 factory = new PaymentGatewayFactory2();
this.gateway = factory.CreatePaymentGateway(method, product);

this.gateway.MakePayment(product);
}
}

Now our Creator is not a pure abstract class but it comes with some default functionality which can
be overridden by the the concrete factories derived from it.

Point of interest
In this article, we looked at simple factory pattern and the scenarios where factory pattern can be
useful. We have implemented a class factory pattern using C#. The article has been written from the
beginner's perspective. I hope this has been informative.

Potrebbero piacerti anche