Link to home
Start Free TrialLog in
Avatar of KaranGupta
KaranGupta

asked on

Factory Pattern

Hi

I am working on an example in which I am creating a calculating system using factory pattern.

For that I have created a Calculator Class. Please check the code in the code section.

Now in the main function I have created the object of calculator class

IResult x = Calculator.getResult(2, 3, CalculationType.Sum);

I have 2 queries

1. Is this a valid factory pattern?
2. How can I get the sum from the code
"IResult x = Calculator.getResult(2, 3, CalculationType.Sum);"

Kindly advice

Regards
Karan Gupta


using System;

namespace ConsoleApplication1
{
    public enum CalculationType
    {
        Sum,
        Difference
    }
    // A Simple Interface
    public interface IResult
    {
        int ReturnResult(int arg1,int arg2);
    }

    public class Sum : IResult
    {
        public int ReturnResult(int arg1, int arg2)
        {
            return (arg1 + arg2);
        }
    }

    public class Difference : IResult
    {
        public int ReturnResult(int arg1, int arg2)
        {
            if (arg1 > arg2)
            {
                return (arg1 - arg2);
            }
            else
            {
                return (arg2 - arg1);
            }            
        }
    }

    public class Calculator
    {
        public static IResult getResult(int a, int b, CalculationType oCalculationType)
        {
            if (oCalculationType == CalculationType.Sum)
            {
                return new Sum();
            }
            else if (oCalculationType == CalculationType.Difference)
            {
                return new Difference();
            }
            else
            {
                throw new ApplicationException("Problem Occurs");
            }
        }
    }
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of ricovox
ricovox
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Meir Rivkin
its not exactly a factory, you simply reflect calculation types as objects.to make it factory you probably need something like this:
 {
        Sum,
        Difference
    }

    public static class CalcFactory
    {
        public static IResult Create(CalculationType calculationType)
        {
            switch (calculationType)
            {
                case CalculationType.Sum:
                    return new Sum();
                    break;
                case CalculationType.Difference:
                    return new Difference();
                    break;
            }
        }
    }

    // A Simple Interface
    public interface IResult
    {
        int ReturnResult(int arg1, int arg2);
    }

    public class Sum : IResult
    {
        public int ReturnResult(int arg1, int arg2)
        {
            return (arg1 + arg2);
        }
    }

    public class Difference : IResult
    {
        public int ReturnResult(int arg1, int arg2)
        {
            if (arg1 > arg2)
            {
                return (arg1 - arg2);
            }
            else
            {
                return (arg2 - arg1);
            }
        }
    }

    public class Calculator
    {
        public static int getResult(int a, int b, CalculationType oCalculationType)
        {
            return CalcFactory.Create(oCalculationType).ReturnResult(a, b);
        }
    }

Open in new window

Here is the whole code, with modifications.

using System;

namespace ConsoleApplication1 {
	public class Program {
		public static void Main() {
			//create the "ICalc" object, which will do the actual work for us
			ICalc x = Calculator.getCalc(CalculationType.Sum);
			int result = x.GetResult(2, 3);
			Console.WriteLine("Result of Sum: " + result);

			x = Calculator.getCalc(CalculationType.Difference);
			result = x.GetResult(2, 3);
			Console.WriteLine("Result of Diff: " + result);
		}
	}

	public enum CalculationType {
		Sum,
		Difference
	}
	// A Simple Interface
	public interface ICalc {
		int GetResult(int arg1, int arg2);
	}

	public class Sum : ICalc {
		public int GetResult(int arg1, int arg2) {
			return (arg1 + arg2);
		}
	}

	public class Difference : ICalc {
		public int GetResult(int arg1, int arg2) {
			if (arg1 > arg2) {
				return (arg1 - arg2);
			} else {
				return (arg2 - arg1);
			}
		}
	}

	public class Calculator {
		public static ICalc getCalc(CalculationType oCalculationType) {
			if (oCalculationType == CalculationType.Sum) {
				return new Sum();
			} else if (oCalculationType == CalculationType.Difference) {
				return new Difference();
			} else {
				throw new ApplicationException("Invalid calculation type.");
			}
		}
	}
}

Open in new window

Notice that I added a Program class that simply uses the Calculator factory to output some results.

sedgwick's answer is also correct, but it was somewhat redundant with my first post. To benefit you most, you could compare sedgwick's full code with my full code. Both are correct factory patterns, but sedgwick added an additional function to directly get the result without returning an IResult object.
(Although this extra function is useful, this type of use actually misses the point a true factory pattern)

Good luck in your coding!
It is a factory pattern and it also qualifies as a factory method pattern http://en.wikipedia.org/wiki/Factory_method_pattern. The two are closely related, one differentiating factor that someone may argue is the parameter (CalculationType oCalculationType), which makes it more close to a factory method than pure-factory.
If you ask my verdict I would say its  a Factory-Method pattern, or a half-cooked builder pattern, as explained below.
How to make it a pure-factory method? Remove all the arguments from the method
public class SumCalculator {
public static ICalc getCalc() {
return new Sum();
}
}
var sumCalc = new SumCalculator();
var sum = sumCalc.getCals();
var subCalc = new SubtractionCalculator();
var sub = subCalc.getCals();
There are also a number of alternatives that you can make now
- Dont use factory, use factory method (as you already did)
- Use an abstract factory pattern, so a factory of a factory. EXAMPLE
public interface Expression {
public object evaluate(int a, int b);
}
public SumExpression : public Expression {
public object evaluate(int a, int b) {
 return a + b;
}
}
// Pure factory
public interface ExpressionFactory {
public IExpression createEvaluator() ;
}
// Pure Concrete factory
public class SumExpressionFactory : ExpressionFactory {
public  IExpression createEvaluator() {
 return new SumExpression();
}
}  
// Top level factory (uses factory method)
public class Calculator {
public static ICalc getCalculator(string operator) {
 if( operator == "sum" }
  return new SumExpressionFactory();
 }
}
}
Expression sum = Calculator.getCalculator("sum").createEvaluator();
int result = sum.evaluate( 10, 22 );
 
- Use Builder pattern, a variation of factory method and factory. EXAMPLE (This by the way is more close in essense to what your original intent appears to be). NOW a and b are no longer redundant.

public interface Expression {
public void setArg1(int a);
public void setArg2(int a);
public object evaluate();
}
public SumExpression : public Expression {
public void setArg1(int a);
public void setArg2(int a);
public object evaluate() {
 return m_a + m_b;
}
}
public class ExpressionBuilder {
public static Expression build(string type, int a, int b) {
 if( operator == "sum" }
  var e = new SumExpression();
  e.setArg1(a);
  e.setArg1(b);
  return e;
 }
}
}
Expression sum = ExpressionBuilder.build("sum", 10, 10);
int result = sum.evaluate();
 
BTW, the difference between builder and factory is that a builder uses composite steps to "construct" an object. The construction here does not mean the object coming into existence but rather coming into a state where it is deemed to be constructed (which depends upon the context).
Composite steps could be constructing different subparts of the object in sequence or even constructing multiple objects and aggregating them together or any other variant.
Avatar of KaranGupta
KaranGupta

ASKER

Hi

Sorry for the late reply.

ricovox:
 I have studied your code and not able to find any difference between your code and mine.

sedgwick:
You have created a method called Create(). I want to know that there is also not much difference in the code. I have come to know how to use the class. But why my class doesn't qualify factory pattern,

ambience:
Is Factory pattern, Abstract Factory and Pure factory patterns are different.


Regards
Karan Gupta
Well first off, I did in fact say that your code qualifies as a Factory pattern.
When I said pure factory, I intended to say a pattern that is not abstract factory or factory method. Probably there is no pure-factory pattern in text books, thats just a term i used to explain things.
I suggest that you take a look at the examples I have posted. I have already tried to explain there what subtle differences can there be between abstract factory etc.
 
Hi

As per the discussion I have created a document. Please let me know if there is any mistake in the tutorial so that I can use it further.



Regards
Karan
Factory-Pattern.docx
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
?????????