?
Solved

Factory Pattern

Posted on 2010-09-01
11
Medium Priority
?
696 Views
Last Modified: 2013-11-13
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
Comment
Question by:KaranGupta
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
  • +1
11 Comments
 
LVL 4

Accepted Solution

by:
ricovox earned 1000 total points
ID: 33576943
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
 
LVL 42

Expert Comment

by:sedgwick
ID: 33576998
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
 
LVL 4

Expert Comment

by:ricovox
ID: 33577018
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
Cloud Training Guides

FREE GUIDES: In-depth and hand-crafted Linux, AWS, OpenStack, DevOps, Azure, and Cloud training guides created by Linux Academy instructors and the community.

 
LVL 4

Expert Comment

by:ricovox
ID: 33577096
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
 
LVL 22

Expert Comment

by:ambience
ID: 33595080
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
 
LVL 22

Expert Comment

by:ambience
ID: 33603900
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
 

Author Comment

by:KaranGupta
ID: 33615163
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
 
LVL 22

Expert Comment

by:ambience
ID: 33616334
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
 

Author Comment

by:KaranGupta
ID: 33626901
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
 
LVL 22

Assisted Solution

by:ambience
ambience earned 1000 total points
ID: 33629151
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
 
LVL 22

Expert Comment

by:ambience
ID: 33638691
?????????
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Transparency shows that a company is the kind of business that it wants people to think it is.
Learn how ViaSat reduced average response times for IT incidents from 10 minutes to 30 seconds.
With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Simple Linear Regression

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question