[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 705
  • Last Modified:

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

0
KaranGupta
Asked:
KaranGupta
  • 5
  • 3
  • 2
  • +1
2 Solutions
 
ricovoxCommented:
Hi Karan,

You are very close.
You need to change only a few things to get this to be a nice factory pattern.

In the factory pattern you create objects with a common interface as you have done. Then you can use "polymorphism" to call a method on the returned object and the result depends on what type of object was created.

After a few small modifications, you will be able to do something like this:

(I renamed IResult to ICalc to make things more clear)

ICalc x = Calculator.getCalc(CalculationType.Sum);
int answer = x.ReturnResult(2, 3);

Open in new window

0
 
Meir RivkinFull stack Software EngineerCommented:
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

0
 
ricovoxCommented:
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

0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
ricovoxCommented:
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!
0
 
ambienceCommented:
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();
 
0
 
ambienceCommented:
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.
0
 
KaranGuptaAuthor Commented:
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
0
 
ambienceCommented:
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.
 
0
 
KaranGuptaAuthor Commented:
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
0
 
ambienceCommented:
Oh well, the code sample appears to be the same that you have posted at the start. I suggest that at the minimum you do these changes.

public class Calculator
{
public static iCalc createOperation(CalculationType oCalculationType)
{
if (oCalculationType == CalculationType.Sum)
{
return new Sum();
}
else if (oCalculationType == CalculationType.Difference)
{
return new Difference();
}
else if (oCalculationType == CalculationType.Multiplication)
{
return new Multiplication();
}
else if (oCalculationType == CalculationType.Division)
{
return new Division();
}
else
{
throw new ApplicationException("Problem Occurs");
}
}
}
iCalc x = Calculator.createOperation(CalculationType.Sum);
int abc = x.ReturnResult(1, 2);
I have done two things
- removed unused parameters a and b
- renamed method so that it sounds more of a create something method.
Finally, I hope you do know that the code sample uses factory-method pattern.
 
0
 
ambienceCommented:
?????????
0

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 5
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now