Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Factory Pattern with .NET Technology

, 13 May 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
I didn’t write about .Net for a long time and it’s always excited to be back. I design and write software solution for a living, and I do that with different technologies(PHP Symfony, Python, Javascript…) but regardless of the technology I always try to respect the S.O.L.I.D principals(http://en.wik

I didn’t write about .NET for a long time and it’s always excited to be back.

I design and write software solution for a living, and I do that with different technologies(PHP Symfony, Python, Javascript…) but regardless of the technology I always try to respect the S.O.L.I.D principals(http://en.wikipedia.org/wiki/SOLID_(object-oriented_design))because violating one of those cause a great collateral damage in your code.

In this article I wanted to share one of my method to write a respectful code (respectful to me, you can have another opinion) using .Net technology.

Let us start with a case study:

The Straw hats pirates (the pirate crew in the one piece anime) contact my company and they want to write a piece of software to automate pizza preparation for them.

Sanji(the cook of the pirate crew) explained to me that in order to prepare pizza we need to

  1. Prepare the Pizza Dough
  2. Prepare the sauce
  3. Add pizza sauce and pizza ingredients to the pizza dough
  4. Put the pizza in the oven

My company assigned this job to me and I wrote this class.

namespace PizzaExample
{
public class PizzaMaker
{
public voidpreparePizza()
{
this.MakeDough();
this.PrepareSauce();
this.AddIngredientsAndSauce();
this.PutInOven();
}
private voidPutInOven()
{
Console.WriteLine("Pizza in Oven");
}
private voidAddIngredientsAndSauce()
{
Console.WriteLine("Adding sauce, cheese,olives and meat");
}
private voidPrepareSauce()
{
Console.WriteLine("Making sauce");
}
private voidMakeDough()
{
Console.WriteLine("Making daugh");
}
}
}

I was happy about my work but only when Sanji come back to me and told that not all of his crew members like the same ingredients and he claimed that Nami is vegetarian and she don’t like to have meat, Chopper another crew member don’t like olives. So I had to rewrite the method AddIngredientsAndSauce to full fit my costumers needs, I refactor it into two methods and it look like this now:

 private voidAddIngredientsAndSauce(String membername="Any")
{
if(membername=="Nami")
Console.WriteLine("Adding cheese and olives");
else if(membername=="Chpper")
Console.WriteLine("Adding cheese and meat");
else
Console.WriteLine("Adding cheese,olives and meat");
}
private voidaddSauce()
{
Console.WriteLine("Adding sauce");
}

Things are good for sometimes, but after a while Sanji come back to me claiming that the Mugiwara(straw hats) pirates have made an alliance with some new big pirate named Law and this pirate want to have sea king fish(a great imaginary fish in one piece) in his pizza.

So I have to add this into my code, the simple thing to do is to go and add a new if statement in the method AddIngredients and it will look like this:

private voidAddIngredients(String membername="Any")
{
if(membername=="Nami")
Console.WriteLine("Adding cheese and olives");
else if(membername=="Chpper")
Console.WriteLine("Adding cheese and meat");
else if(membername=="Chpper")
Console.WriteLine("Adding cheese,olives, meat and see king fish");
else
Console.WriteLine("Adding cheese,olives and meat");
}

But this a huge violation to the open close principal, the open close principal suggest that a class should be open for extension and close for changes(http://en.wikipedia.org/wiki/Open/closed_principle).

This is why we should use the power of object oriented paradigm to overcome this problem. For that I’m going to use abstraction, inheritance and polymorphism to come up with a good solution.

First thing to come to our mind is to create a class responsible for making pizza for each member; each of those classes will inherit from the mother class PizzaMaker. The PizzaMaker class will implement the general implementation for the AddIngredient method and the each of the other child class will override this method to add the suitable ingredients for the member. So we have this new class diagram

This is the new AddIngredientPizza of the Pizzamaker class

protected virtual void AddIngredients()
{
Console.WriteLine("Adding cheese,olives and meat");
}
This is the NamiPizzaMaker class:
namespace PizzaExample
{
public class NamiPizzaMaker:PizzaMaker
{
protected override void AddIngredients()
{
Console.WriteLine("Adding cheese and olives");
}
}
}

Now the question is how and where to know which class to instantiate (PizzaMaker, NamiPizzaMaker, ChopperPizzaMaker or LawPizzaMaker). Well the first option is to give that responsibility to higher layer (UI layer) but this way you will create a dependency between layers and violate the Dependency injection principal. So the best way is to go and create a factory class that will be responsible for knowing how to instantiate the class.

The factory class will look like that:

namespace PizzaExample
{
public class PizzaFactory
{
public static PizzaMaker getPizzaMaker(Stringmember)
{
if (member == "Nami")
return newNamiPizzaMaker();
if (member == "Chopper")
return newChopperPizzaMaker();
if (member == "Law")
return newLawPizzaMaker();
else
return newPizzaMaker();
}
}
}

Well now we protected our AddIngredient Method from violating the open close principals, also we reduce the dependency by adding the factory class that will be responsible for creating the suitable class.

But still if we analyze the static method getPizzaMaker of the PizzaFactory class we will notice couple of bad design smell

  1. We have to deal with hardcoded strings "Nami","Low" and "Chopper"(hardcoded strings are the root of huge bugs and design problems)
  2. Each time we add new child class of PizzaMaker we need to modify the getPizzaMaker method again that violate the Open/Close principal
  3. The method is static(I will explain why this is bad in another article about testing)

Well my solution to 1 and 2 problem is to create an xml configuration file that knows for each member what class to instantiate.This XML structure will hold xml elements, each element will have two properties, one is the name of the member and two the name of the class to instantiate.

Example for the team member Nami we have the class NamiPizzaMaker class that know how to make pizza for Nami(Single responsibility principal), for the factory class to able to return an instance of the NamiPizzaMaker class we have to add this xml element

<add member="Nami" classname="NamiPizzaMaker"/>

The getPizzaMaker method of the PizzaFactory class will look into the xml file, get all the elements, iterate them and when the name of the member equals the "member" property in the xml element the method will get the "classname" property from that same xml element as string and create an instance of the class from string using the Activator.CreateInstance("nameoftheclass").

So each time we have a new pizza maker all you have to do is to create a new class that is a subclass of PizzaMaker class and add a new xml element to the configuration file, like that

<add member="new member" classname="NewSubsclassofPizzaMaker"/>.

To create this xml configuration file you have two solutions, one solution will creating a new xml file called pizzamakers.xml and all your xml elements in it, but with this solution will have at least 3 or 4 xml files that should be maintained and this is not very productive.

Second solution will be using App.config or web.config, .Net offer many build in classes in the namespace System.Configuration that helps you get access to this configuration file. So I will use this file to put my custom configuration and in the next section I will describe how to do it.

NB: All the previous concepts are general concepts that are valid with any technology that use object oriented architecture, but the next section is .Net specific section because we going to use .NET built in features.

First step is to add a new configuration file to your project and you should get a new file called App.config .

Second Step: Create a custom section

.NET framework has a built in classes to access configuration file all those classes are under the namespace System.Configuration.

And with the ConfigurationManager class you can access the elements of any section in your configuration file including your custom sections using the GetSection method. ConfigurationManager.GetSection("nameofthesection");

But before add any custom sections to the xml config file and in order for the ConfigurationManager class to be able to recognize your custom section you need to create a subclass of the class ConfigurationSection.

I won’t get in the details of how to create a custom configuration section, you can look into it in the internet.

We need this class in order to get a custom section called PizzaMakerSection

namespace PizzaExample
{
public class PizzaMakersSection:ConfigurationSection
{
[ConfigurationProperty("", IsRequired=true, IsDefaultCollection=true)]
public PizzaMakerElementCollectionPizzaMaker
{
get
{
return (PizzaMakerElementCollection)this[""];
}
set
{ this[""] = value; }
}
}
public class PizzaMakerElementCollection: ConfigurationElementCollection{
protected override ConfigurationElement CreateNewElement()
{
return new PizzMakerElement();
}
protected override object GetElementKey(ConfigurationElementelement)
{
return ((PizzMakerElement)element).className;
}
}
public class PizzMakerElement : ConfigurationElement
{
[ConfigurationProperty("member",IsRequired=true)]
public StringMemeber { get { return(string)this["member"]; } set{ this["member"] = value; } }
[ConfigurationProperty("classname",IsRequired=true)]
public stringclassName
{
get
{
return (string)this["classname"];
}
set
{
this["classname"] = value;
}
}
}
}

and the App.config file will look something like that:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="pizzaMakerSection"
type="PizzaExample.PizzaMakersSection,PizzaExample"
/>
</configSections>
<pizzaMakerSection>
<add member="Nami" classname="PizzaExample.NamiPizzaMaker"/>
<add member="Chopper" classname="PizzaExample.ChopperPizzaMaker"/>
<add member="Law" classname="PizzaExample.LawPizzaMaker"/>
<add member="Any" classname="PizzaExample.PizzaMaker"/>
</pizzaMakerSection>
</configuration>

Third Step: Modify the factory to be able to read from App.config file and instantiate the appropriate class

namespace PizzaExample
{
public class PizzaFactory
{
public static PizzaMaker getPizzaMaker(Stringmember)
{
PizzaMakersSection config = (PizzaMakersSection)ConfigurationManager.GetSection("pizzaMakerSection");
foreach (PizzMakerElementelement in config.PizzaMaker)
{
if(element.Memeber.Equals(member))
{
try
{
var type = Type.GetType(element.className);
PizzaMaker instance = (PizzaMaker)Activator.CreateInstance(type);
return instance;
}
catch (Exceptionex)
{
//log exception
return null;
}
}
}
return null;
}
}
}

Note that you can add PizzaMaker subclasses for each new member without having to change anything in the code of the method getPizzaMaker of the PizzaFactory class and without violating the open/close principal, all you have to do is

  1. create a subclass of the PizzaMaker class
  2. Add a new xml element to the pizzaMakerSection in the App.config file that have the member property and the classname property.

Conclusion

This is my method to implement the factory pattern in .NET, I hope that was helping and if you have any better methods or advices please share it with me.

License

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

Share

About the Author

Njim Mahdi
CEO DISYCS
Tunisia Tunisia
I'm a developer, software architect and a I have my own start up, I' worked with different technologies(.Net , java j2ee, Python , Python django, PHP, PHP symfony...). Our company is working on the distributed systems and cloud solution(IAAS tools, SAAS architecture and software) I like to read about technologies and I like also to blog and write articles.
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun4-Sep-14 0:33 
GeneralAwesome article PinmemberJean-Francois Gouin14-May-14 7:27 
GeneralRe: Awesome article PinmemberNjim Mahdi20-May-14 7:43 
GeneralInteresting to read PinmemberHoussem_Dellai13-May-14 9:07 
GeneralRe: Interesting to read PinmemberNjim Mahdi13-May-14 10:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411028.1 | Last Updated 13 May 2014
Article Copyright 2014 by Njim Mahdi
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid