Thursday, March 28, 2013

Factory Method Pattern

Factory method pattern provides a way for extensibility. It is a creational pattern. Factory Method pattern, is a method that can be used to create one of the Implemented contracts (Instance of a Concrete class) among choices. Usually creational patterns hides the instantiation from the user.

 

Scenario:

You want to provide choice to your class users in a specific situation. Those choices fulfils the contract in different ways.

 

Basic Solution For this Scenario:

For example you have a part of code that has to add or multiply two values based on a configuration. You will implement this like

  • You will write two methods for Add and Multiply.
  • You will ask you user to call you methods based on the configuration.

 

void Calc(int n1, int n2)

{

    char op= GetOpConfig();

    int r;

    switch(op)

    {

    case ‘+’:

        r=Add(n1, n2);

    case ‘*’:

        r=Multiply(n1, n2);

    }

    Display(r);

}

 

Problem:

User has to change the code when you are implementing new methods like Subtract. User has to add another case to implement this.

 

void Calc(int n1, int n2)

{

    char op= GetOpConfig();

    int r;

    switch(op)

    {

    case ‘+’:

        r=Add(n1, n2);

    case ‘*’:

        r=Multiply(n1, n2);

    case ‘-’:

        r=Subtract(n1, n2);

    }

    Display(r);

}

 

So you both has to alter the code when the requirement changes.

 

Solution:

You can use Factory Method pattern to solve this issue.

  • Understand the scenario and bring up a common contract from it (basically with a class, interface or delegate). The common contract should be abstract superset.
  • Here what I mean by superset is, it should cover all the requirements.
  • Consider you are implementing a negation operation that requires only one operand. As you are making it common, you have to use the second operator in the abstract but leave it ignored during negation implementation.
  • Consider you are implementing ternary operation that requires three operators, then the super class should cover all.
  • If you have completed the factory method with two operators and you have a new requirement to support ternary operator that is almost a BREAKING CHANGE.
  • Implement your different implementations of contract with that superset’s abstract.
  • Implement a factory method, that receives a code for a specific instance (which is given to the user in a document) and returns instance of implemented contract based on the received code.
  • Document the usage with following details and give it to the user.
  • Contract Details such as properties and methods defined in the contract

Factory method parameters and possible values Factory method is implemented.

 

Implementation:

Ok. Lets implement a sample for the above requirements.

 

Understanding the scenario

  • We are going to provide the users with a way to calculate.
  • We want to make it extensible so that new operators can be added later.

 

Creating Common Contract

 

  • Calculation basically requires two operands
  • Calculation will return one result.
  • For unary operator, user won’t give second operand. Implemented contract will ignore the second operator.

 

public abstract class Operation {
    public int Num1 { get; set; }
    public int Num2 { get; set; }
    public int Result { get; set; }
    public abstract void Calc();
}

 

Implementing Contract

  • Above contract can be implemented for Add and Multiply as follows

public class Add : Operation {
    public override void Calc() {
        Result= Num1 + Num2;
    }
}

public class Multiply : Operation {
    public override void Calc() {
        Result = Num1 * Num2;
    }
}

 

Implementing Factory Method

 

  • Factory method can be implemented with a single static method as coded below

public class Calculation {
    public static Operation GetOperation(char op) {
        switch (op) {
            case '+': return new Add();
            case '*': return new Multiply();
        }
        return null;
    }
}

 

 

Using Factory Method

 

  • Calling factory method is easy. It is just like calling regular methods.

var cal = Calculation.GetOperation(op);
cal.Num1 = n1;
cal.Num2 = n2;
cal.Calc();
var ret = cal.Result;

 

  • value for op can be hard coded or from a configuration.

 

Extending with Factory Method Pattern

  • New implementation can be added anytime without affecting the users code.
  • Adding a subtract will be easy as mentioned below

public class Subtract : Operation {
    public override void Calc() {
        Result = Num1 - Num2;
    }
}

  • Adding a simple case block will be enough in Factory method.

case '-': return new Subtract();

 

We can implement the same using interfaces or delegates as contracts

No comments:

Post a Comment