In this article we will learn about Factory Pattern and it's implementation
Introduction
Factory pattern comes under the category of Creational Pattern that promises the best way to create objects.The essence of the Factory 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."(Quoted from Gang Of Four)
If we need the creation of many different types of objects when all derived from a common base type, Factory Pattern is the choice. Factory pattern does this by the help of Factory Method.It defines a method for creation of objects to sub classes.This means that a base class(abstract class) or interface is defined and subclasses which implement the interface / abstract class , are left to object instantiation. However, client code doesn't create an object against this interface. At run time, the Factory Method accepts a desired object as a parameter and returns a base class pointer to a new instance of that object.This pattern works best when a well-designed interface is used for the base class, so there is no need to cast the returned object.
Objective
In this article we will look into as how Factory Method is useful in object creation.This article will use invocation of workflow services after creation of their instances deferred till run time by the help of factory method.The concrete classes are the windows services here.
Case Study
This happens to be a real time scenario which we encounter some times back. I will extract the needed portion from the scenario that will fit for our learning purpose.
Once we had to interact with the Workflows from the Windows Services and the invocation of the Workflows (instance creation of the Workflow classes) were kept hidden from the client i.e. Windows Services. In this example, we will look into as how we factory pattern can help us in accomplishing so.
Step 1: Create the Workflow Project
First of all, let us create a "Sequential Workflow Console Application
" project, and then add two Sequential workflows namely FirstSequentialWorkflow and SecondSequentialWorkflow.
Add a Code Activity component in the FirstSequentialWorkflow (FirstSequentialWorkflow.cs) and in the Execute Code event write the below code
private
void codeActivity1_ExecuteCode(object sender, EventArgs e){
Console.WriteLine("This workflow was invoked by {0}", WorkFlowInvokedBy);Console.ReadKey();}
Follow the same step for SecondSequentialWorkflow(SecondSequentialWorkflow.cs)
private
void codeActivity1_ExecuteCode(object sender, EventArgs e){
Console.WriteLine("This workflow was invoked by {0}", WorkFlowInvokedBy);Console.ReadKey();}
We will pass the WorkFlowInvokedBy property value from the client application and that will be displayed at runtime.
Now compile the project and it will build successfully
Step 2: Create the Workflow Factory Service Project
Now create a "Class Library" project and name it as WorkflowFactoryService.Let us first look into the UML class diagram
We can figure out that, the two Concrete classes viz ConcreteFirstWorkflow(ConcreteFirstWorkflow.cs) and ConcreteSecondWorkflow(ConcreteSecondWorkflow.cs) are implementing the IInstance interface's GetInstance() method.
IInstance.cs
public
interface IInstance{
Type GetInstance();}
ConcreteFirstWorkflow.cs
public class ConcreteFirstWorkflow : IInstance{
public Type GetInstance(){
return typeof(ConcreteWorkFlows.FirstSequentialWorkflow);}
}
ConcreteSecondWorkflow.cs
public class ConcreteSecondWorkflow : IInstance{
public Type GetInstance(){
return typeof(ConcreteWorkFlows.SecondSequentialWorkflow);}
}
The WorkflowFactory (WorkflowFactory.cs) class's (it is the Factory class) GetObject method (it is the factory method) return the needed workflow class instance depending on the WorkflowType parameter passed to it.
WorkflowFactory.cs
public
class WorkflowFactory{
public IInstance GetObject(Constants.WorkflowType WorkflowType){
IInstance instance = null;switch (WorkflowType){
case Constants.WorkflowType.FIRST_WORKFLOW:instance =
new ConcreteFirstWorkflow();break;case Constants.WorkflowType.SECOND_WORKFLOW:instance =
new ConcreteSecondWorkflow();break;}
return instance;}
}
That's all about the Factory Method.Now we need to expose some service to the external client. For that purpose we have IFactoryService(IFactoryService.cs) interface
public
interface IFactoryService{
void Start();void Stop();Constants.WorkflowType WorkflowType {
get; set; }}
The Start() method will start the Workflow runtime engine.
The Stop() method will stop the Workflow runtime engine.
The client i.e. the Windows Services has to register to the WorkflowType property inorder to determine which Workflow service they are interested in
The implementing class for this interface (i.e. IFactoryService) is the FactoryService (FactoryService.cs).Below is a full impplementation for the same
public
class FactoryService : IFactoryService{
WorkflowRuntime workflowRuntime = null;WorkflowInstance instance = null;
public FactoryService()
{
workflowRuntime = new WorkflowRuntime();
}
#region
IFactoryService Memberspublic Constants.WorkflowType WorkflowType { get; set; }
public void Start()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteWorkflow));
}
public void Stop()
{
workflowRuntime.StopRuntime();
}
#endregion
#region
Private Methods
private void ExecuteWorkflow(object state)
{
try
{
Dictionary dictParams = new Dictionary();switch (WorkflowType){
case Constants.WorkflowType.FIRST_WORKFLOW:dictParams.Add(
"WorkFlowInvokedBy", "First Window Service");break;case Constants.WorkflowType.SECOND_WORKFLOW:dictParams.Add(
"WorkFlowInvokedBy", "Second Window Service");break;
}
instance = workflowRuntime.CreateWorkflow(GetWorkflowInstance(), dictParams);
instance.Start();
}
catch (Exception ex)
{
throw ex;
}
}
private Type GetWorkflowInstance()
{
WorkflowFactory factory = new WorkflowFactory();
return factory.GetObject(WorkflowType).GetInstance();
}
#endregion
}
The presence of the QueueUserWorkItem with the Callback method ensures that the OnStart() method of the Windows Service will run as expected without consuming more execution time if many workflow instances are created also.If we need to pass any parameter to the workflow, the we need to do so via a
Dictionary
<string, object> dictParams = new Dictionary<string, object>();
object.In the
ExecuteWorkflow method,we are checking the
WorkflowType and then adding the needed value to the dictionary object. Then we are creating the WorkFlow instance by using the
GetWorkflowInstance() method that returns
Type.This method, internaly calls the factory method to create the workflow instance being requested by the Windows Service applications.
Step 3: Create the Windows Service Project
Finally we will create two Windows Service project - one by the name FirstWindowService, the other by the name SecondWindowService.
The implementation of the Service1.cs in FirstWindowService
is as under
public
partial class Service1 : ServiceBase{
IFactoryService iService;public Service1(){
InitializeComponent();
iService =
new FactoryService();}
protected override void OnStart(string[] args){
iService.WorkflowType =
Constants.WorkflowType.FIRST_WORKFLOW;iService.Start();
}
protected override void OnStop(){
iService.Stop();
}
}
The implementation of the Service1.cs in SecondWindowService
is as under
public
partial class Service1 : ServiceBase{
IFactoryService iService;
public Service1()
{
InitializeComponent();
iService = new FactoryService();
}
protected override void OnStart(string[] args)
{
iService.WorkflowType = Constants.WorkflowType.FIRST_WORKFLOW;
iService.Start();
}
protected override void OnStop()
{
iService.Stop();
}
}
As we can figure out that the invocation part is really straight forward with the difference being in registering the WorkflowType
As a last step, we have to create the project installers and then install the service. Finally run the service and enjoy how it behaves.
N.B.~Those who don't know how to create,install and run a windows service, here is an article about the same.
References
Factory Method
Conclusion
Factory pattern deals with how an object is created. A factory class will have a factory method that returns a new instance of a class based on the parameter being passed.Hope this article will be helpful whoa are interested in knowing and implementing Factory pattern.
Zipped file is attached herewith.Thanks for reading