Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

The Factory Pattern

4.76/5 (23 votes)
27 Mar 2010CPOL7 min read 1   965  
A Design Pattern that can make your application architecture more flexible and less fragile
factory.png

Introduction

Factory pattern is the most widely used pattern in the software engineering world. This pattern introduces loose coupling between classes which is the most important principle one should consider and apply while designing the application architecture. Loose coupling can be introduced in application architecture by programming against abstract entities rather than concrete implementations. This not only makes our architecture more flexible but also less fragile.

Think Coupling When Using NEW

When you are using “new” keyword in .NET or Java and/or newObj in other languages, you are not just creating an object but under the hood you are also introducing coupling within your application. It doesn’t mean you don’t have to use it anymore as it’s the only way of instantiating an object, but we should find a way to do it more effectively because we have to cater to an important factor in software engineering (or even in life which remains constant) and that’s “CHANGE”. Let’s have a look at an example:

VB

VB.NET
Dim myBat As New HardBallBat()

C#

C#
Bat myBat = new HardBallBat();

And we most often extend this approach when we have a set of related classes, e.g.

VB

VB.NET
If (hardball)
   Dim myBat As Bat = New HardBallBat()
ElseIf (tapeball)
   Dim myBat As Bat = New TapeBallBat()
ElseIf (plasticball)
   Dim myBat As Bat = New PlasticBallBat()

C#

C#
if (hardball)
    Bat myHardBallBat = new HardBallBat();
else if (tapeball)
    Bat myTapeBallBat = new TapeBallBat();
else if (plasticball)
    Bat myPlasticBallBat = new PlasticBallBat();

Here, we are instantiating several concrete implementations depending on the condition evaluated at runtime. So, what’s wrong with this approach? There might be dozens of classes which you may add in the future and can also remove some which are of no use to you which shows that this code is not closed for modification, you have to reopen it and do the modification but a good architecture should follow a principle, i.e., the design should be opened for extension but closed for modification. And this sort of code may also be scattered everywhere in your application which can be a maintenance nightmare.

Separate the Aspects that Vary

Now let’s extend the example provided above and consider there is a shop down the road which is selling top quality bats and you have been assigned the task to develop an application for that shop, you might end up writing code something like this in its OrderBat() method:

VB

VB.NET
Public Function OrderBat() As Bat

        Dim myBat As New Bat()

        myBat.clean()
        myBat.applyGrip()
        myBat.applyLogo()
        myBat.applyCover()
        myBat.pack()

        Return myBat

End Function

C#

C#
public Bat OrderBat()
{
    Bat myBat = new Bat();

    myBat.clean();
    myBat.applyGrip();
    myBat.applyLogo();
    myBat.applyCover();
    myBat.pack();

    return myBat;
}

And an extended version of this example might be having a condition evaluated at runtime according to customer’s choice of the bat he/she wants to buy and every concrete implementation extends the base class which is “Bat”. Therefore:

VB

VB.NET
Private Function OrderBat(ByVal choice As String) As Bat

    Dim myBat As Bat

    Select Case choice

        Case "hardball"
    myBat = New HardBallBat()

        Case "softball"
    myBat = New SoftBallBat()

        Case "plasticball"
    myBat = New PlasticBallBat()

    End Select

    myBat.clean()
    myBat.applyGrip()
    myBat.applyLogo()
    myBat.applyCover()
    myBat.pack()

Return myBat

End Function

C#

C#
private Bat OrderBat(string choice)
{
   Bat myBat = default(Bat);

   switch (choice) 
   {
         case "hardball":
            myBat = new HardBallBat();
            break;
        case "softball":
            myBat = new SoftBallBat();
            break;
        case "plasticball":
            myBat = new PlasticBallBat();      
            break;
    }

   myBat.clean();
   myBat.applyGrip();
   myBat.applyLogo();
   myBat.applyCover();
   myBat.pack();

   return myBat;
}

Now you might have analyzed that this method is not closed for modification because if in the future they decided to sell any new bat or want to remove something from their collection, you have to again reopen it and do the modification but you might have also analyzed there are certain other parts in the method that don’t need to be changed or at least don’t have any chance of change in the future, i.e.

VB.NET
myBat.clean()
myBat.applyGrip()
myBat.applyLogo()
myBat.applyCover()
myBat.pack()

Then why not separate those aspects of code that change so that we just have to worry about that part of our code, i.e.:

VB

VB.NET
Select Case choice

    Case "hardball"
	myBat = New HardBallBat()

    Case "softball"
	myBat = New SoftBallBat()

    Case "plasticball"
	myBat = New PlasticBallBat()

End Select

C#

C#
switch (choice) 
{  
   case "hardball": 
      myBat = new HardBallBat(); 
      break; 

   case "softball": 
      myBat = new SoftBallBat(); 
      break; 

   case "plasticball": 
      myBat = new PlasticBallBat(); 
      break; 
}

As we are now aware what is changing in our code and what isn’t, we can now encapsulate it. But wait! The code that is varying as we can see contains the object creation logic and we want to isolate it from our client so in which method we should put it? That’s right, Factory method! Because any method that deals with the object creation can be called as factory method.

Simple Bat Factory

Our client will use this factory to get the object it wants and beauty of this pattern is that it doesn’t let client to change its code to get the thing it wants, the client just has to demand from the factory for the object it needs, as this is what factory is for so let's define a simple Bat factory:

VB

VB.NET
Public MustInherit Class BatFactory
    MustOverride Function CreateBat(ByVal choice As String) As Bat
End Class

C#

C#
public abstract class BatFactory
{
    public abstract Bat CreateBat(string choice);
}

This is our base factory class which must be implemented by all the factories that want to supply us bats because this is what our client recognizes and can only work with. So let’s define it:

VB

VB.NET
Public Class SimpleBatFactory
    Inherits BatFactory

    Overrides Function CreateBat(ByVal choice As String) As Bat

        Dim myBat As Bat

        Select Case choice

            Case "hardball"
                myBat = New HardBallBat()

            Case "softball"
                myBat = New SoftBallBat()

            Case "plasticball"
                myBat = New PlasticBallBat()

        End Select

        Return myBat

    End Function

End Class

C#

C#
public class SimpleBatFactory : BatFactory
{  
    public override Bat CreateBat(string choice)
    {
        Bat myBat = default(Bat);
 switch (choice) 
{
            case "hardball":
                myBat = new HardBallBat();
                break;
            case "softball":
                myBat = new SoftBallBat();
                break;
            case "plasticball":
                myBat = new PlasticBallBat();
                break;
        }
        return myBat;
    }
   }

Now our client will simply use the CreateBat method to get the bat of customer’s choice provided the returned object implements the required interface. We can now modify the client code and this would be the last modification to our client class, i.e.

VB

VB.NET
Public Function OrderBat(ByVal choice As String) As Bat

           Dim myBat As Bat = _factory.CreateBat(choice)

           myBat.clean()
           myBat.applyGrip()
           myBat.applyLogo()
           myBat.applyCover()
           myBat.pack()

           Return myBat

       End Function

C#

C#
public Bat OrderBat(string choice)
{
    Bat myBat = _factory.CreateBat(choice);
    myBat.clean();
    myBat.applyGrip();
    myBat.applyLogo();
    myBat.applyCover();
    myBat.pack();
    return myBat;
}

Our Order Bat method is now delegating object creation responsibility to our factory method. Putting it all together, the client class will certainly look like:

VB

VB.NET
Public Class SuperShop

    Dim _factory As BatFactory

    Public Sub New(ByVal factory As BatFactory)

        Me._factory = factory

    End Sub

    Public Function OrderBat(ByVal choice As String) As Bat

        Dim myBat As Bat = _factory.CreateBat(choice)

        myBat.clean()
        myBat.applyGrip()
        myBat.applyLogo()
        myBat.applyCover()
        myBat.pack()

        Return myBat

    End Function

End Class

C#

C#
public class SuperShop
{
    BatFactory _factory;
    public SuperShop(BatFactory factory)
    {
        this._factory = factory;
    }
    public Bat OrderBat(string choice)
    {
        Bat myBat = _factory.CreateBat(choice);
        myBat.clean();
        myBat.applyGrip();
        myBat.applyLogo();
        myBat.applyCover();
        myBat.pack();
        return myBat;
    }
}

Now while instantiating the object of SuperShop, we just have to pass it the reference of the factory we want to get our bats from, e.g.:

VB

VB.NET
'A factory that will handle the object creation
Dim factory As New SimpleBatFactory()

'Our shop will now use this factory to create the required object
Dim shop As New SuperShop(factory)
shop.OrderBat("hardball")

C#

C#
//A factory that will handle the object creation
SimpleBatFactory factory = new SimpleBatFactory();
   
//Our shop will now use this factory to create the required object
SuperShop shop = new SuperShop(factory);
shop.OrderBat("hardball");

Client doesn’t need to worry about the object instantiation logic as it has now been taken care by our factory.

Loose Coupling and Flexibility

Another important thing to note here is despite the fact that we have effectively isolated the code from the client class and now our maintenance is in one place but it also introduces flexibility and loose coupling in our architecture. If, for example, in the future SuperShop decided to take bats from other manufacturer rather than form SimpleBatFactory what we just have to do is pass the instance of that factory, Simple and neat? For example:

VB

VB.NET
Public Class CABatFactory
       Inherits BatFactory

       Overrides Function CreateBat(ByVal choice As String) As Bat

           Dim myBat As Bat

           Select Case choice

               Case "hardball"
                   myBat = New CAHardBallBat()

               Case "softball"
                   myBat = New CASoftBallBat()

               Case "plasticball"
                   myBat = New CAPlasticBallBat()

           End Select

           Return myBat

       End Function

   End Class

C#

C#
public class CABatFactory : BatFactory
{
    public override Bat CreateBat(string choice)
    {
        Bat myBat = default(Bat);
        switch (choice) {
            case "hardball":
                myBat = new CAHardBallBat();
                break;
            case "softball":
                myBat = new CASoftBallBat();
                break;
            case "plasticball":
                myBat = new CAPlasticBallBat();
                break;
        }
        return myBat;
    }
}

This is the factory that will now provide us with the bats from our preferred manufacturer and our object instantiation will now use this factory instead:

VB

VB.NET
Dim factory As New CABatFactory()

Dim shop As New SuperShop(factory)
shop.OrderBat("hardball")

C#

C#
CABatFactory factory = new CABatFactory(); 

SuperShop shop = new SuperShop(factory); 
shop.OrderBat("hardball");

As you can see, we haven’t changed the client’s code at all, and now the client is able to work with the objects returned by the factory of our choice.

More Control

One approach to factory pattern have been described above but what if you want to have more control over how the object can be instantiated and only the things you want, would be open for modification by third parties? Let’s say the SuperShop wants to have franchises everywhere in the country but they want to have some quality control also so that the franchisees may take bats from their preferred suppliers but the other quality measures cannot be altered in any way! Don’t you think they are really in need of a framework here to easily manage all of the requirements of their franchisee?

A Framework for BatFactory

SuperShop can provide this Framework to their franchisees so that they can implement the object creation logic by themselves but still can have the power to manage and enforce their quality measures. Let’s look at the altered version of our BatFactory Class.

VB

VB.NET
Public MustInherit Class BatFactory

    Public Function OrderBat(ByVal choice As String) As Bat

        Dim myBat As Bat = Me.CreateBat(choice)

        myBat.clean()
        myBat.applyGrip()
        myBat.applyLogo()
        myBat.applyCover()
        myBat.pack()

        Return myBat

    End Function

    MustOverride Function CreateBat(ByVal choice As String) As Bat

End Class

C#

C#
public abstract class BatFactory
{
    public Bat OrderBat(string choice)
    {
        Bat myBat = this.CreateBat(choice);
        myBat.clean();
        myBat.applyGrip();
        myBat.applyLogo();
        myBat.applyCover();
        myBat.pack();

      return myBat;
    }
    public abstract Bat CreateBat(string choice);
}

So, what we have done here? We have just included the factory method inside our base class (an abstraction) that will delegate the responsibility of object creation to its derived classes. Now the implementers of this class can’t change any of our quality measures because we have just localized them and on the other hand can freely provide their own object instantiation logic by overriding the CreateBat() function. OrderBat function is not really interested in how the objects are created provided the returned type implemented the interface required.

Wait There’s More

Before concluding this article, why not let one our franchisee implement our framework and see how they will actually use it?

VB

VB.NET
Public Class SuperShopFranchisee
      Inherits BatFactory

      Overrides Function CreateBat(ByVal choice As String) As Bat

          Dim myBat As Bat

          Select Case choice

              Case "hardball"
                  myBat = New AddidassHardBallBat()

              Case "softball"
                  myBat = New AddidassSoftBallBat()

              Case "plasticball"
                  myBat = New AddidassPlasticBallBat()

          End Select

          Return myBat

      End Function

  End Class

C#

C#
public class SuperShopFranchisee : BatFactory
{
    public override Bat CreateBat(string choice)
    {
        Bat myBat = default(Bat);
        switch (choice) 
       {
            case "hardball":
                myBat = new AddidassHardBallBat();
                break;
            case "softball":
                myBat = new AddidassSoftBallBat();
                break;
            case "plasticball":
                myBat = new AddidassPlasticBallBat();
                break;
        }
        return myBat;
    }
}

As you can see, our franchisee have successfully provided its own implementation, now they just have to instantiate the object of their shop and they are good to go:

VB

VB.NET
Dim franchisee As New SuperShopFranchisee
      franchisee.OrderBat("hardball")

C#

C#
SuperShopFranchisee franchisee = new SuperShopFranchisee(); 
franchisee.OrderBat("hardball");

OrderBat will confirm that all of quality measures of franchiser have been followed and delegate the object creation responsibility to the factory method implemented by our franchisee to get the object as OrderBat only concerned with the object it needs not the creation logic because this is what factory method is for.

Some Theory

Now I think we are in a position to understand what the official definition actually said about this pattern after all, as understanding the pattern from the definition first is quite difficult for me at least, because design pattern are more of a practical kind of thing. So, here we go:

“The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”

And now miraculously this definition started making sense to me!

Conclusion

One should keep in mind the efforts which have already been done on the problem which one is facing. It's like not to reinvent the wheel and to learn from others' experiences!

References

History

  • 27th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)