Factory pattern in C#

I was a bit able to understand Factory Pattern and came up with this implementation.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Enter the fruit name to get the Fruit!");
        string fruit = Console.ReadLine();

        FruitsList fruits;
        if (Enum.TryParse(fruit, true, out fruits))
        {
            var fruitWeight = GetFruitWeight(fruits);
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("Fruit Name is undefined!");
            Console.ReadLine();
        }
    }

    private static object GetFruitWeight(FruitsList fruitNumber)
    {
        switch (fruitNumber)
        {
            case FruitsList.Banana:
                return new Banana();
            case FruitsList.Apple:
                return new Apple();
        }

        return null;
    }
}

internal class Banana : IFruits
{
    public float ReturnFruitWeight()
    {
        return (float)10.00;
    }
}

public interface IFruits
{
    float ReturnFruitWeight();
}

public class Apple : IFruits
{
    public float ReturnFruitWeight()
    {
        return (float)30.00;
    }
}

public enum FruitsList
{
    Apple,
    Banana,
}

The whole idea of mine (from the theoretical understanding) is that the GetFruitWeights function shall accept an enum type and then return the fruit weight. I was able to get the object of a particular Fruit but now stuck up with how from the Fruit object, I get the weight of the fruit.

Also, to add to my doubts list, Am I really following Factory pattern in this implementation? And also, some materials in the internet uses an abstract class too ? What should I follow ? A interface implementation or should I use an abstract class and override it ?

Thanks in advance for your help.

Upvotes: 2

Views: 2329

Answers (4)

Sani Huttunen
Sani Huttunen

Reputation: 24375

I'd do something like this:

public interface IFruit
{
    string Name { get; set; }
    decimal GetWeight();
}

public class Fruit : IFruit
{
    protected decimal Weight;

    public string Name { get; set; }

    public decimal GetWeight()
    {
        return Weight;
    }
}

public class Apple : Fruit
{
    public Apple()
    {
        Name = "Granny Smith";
        Weight = (decimal) 2.1;
    }
}

public class Banana : Fruit
{
    public Banana()
    {
        Name = "Cavendish";
        Weight = (decimal) 1.5;
    }
}

public enum FruitType
{
    Apple,
    Banana        
}

public static class FruitFactory
{
    public static IFruit CreateFruit(FruitType f)
    {
        switch(f)
        {
            case FruitType.Banana: return new Banana();
            case FruitType.Apple: return new Apple();
            default: return null;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var apple = FruitFactory.CreateFruit(FruitType.Apple);
        var banana = FruitFactory.CreateFruit(FruitType.Banana);

        Console.WriteLine(apple.Name + " " + apple.GetWeight());
        Console.WriteLine(banana.Name + " " + banana.GetWeight());
    }
}

Upvotes: 2

S.N
S.N

Reputation: 5140

You can either follow abstract type or interface approach to implement factory method. As an example, your case can be addressed through abstract since you intend to return one subclass.

//Fruit base
    public abstract class Fruit
    {
        protected abstract string GetWeight();
    }
    public class Apple:Fruit
    {
        protected override string GetWeight()
        {
            return "I am from Apple";//replace with your implementation
        }
    }
    public class Banana : Fruit
    {
        protected override string GetWeight()
        {
            return "I am from Banana";//replace with your implementation
        }
    }



private static Fruit GetFruitWeight(string fruitNumber)
        {
            switch (fruitNumber)
            {
                case "Banana":
                    return new Banana();
                case "Apple":
                    return new Apple();
            }

            return null;
        }

Now where should we use interface approach ?

Personally, I follow interface approach in a factory method where i expect to return service. Eg. Assume a factory method which return a email sender service, where I could have service implementation for either outlook or some other email service.

public class Outlook:ISender
    {

        public void SendEmail()
        {
            //Write implementation on how OL send email.
        }
    }
    public class OtherEmail : ISender
    {

        public void SendEmail()
        {
            //Write implementation on how other email send email.
        }
    }
    public interface ISender
    {
        void SendEmail();
    }
    public class EmailFactory
    {

        public static ISender GetEmailProvider(string type)
        {
            if (type == "outlook")
                return new Outlook();
            return new OtherEmail();
        }
    }

Upvotes: 3

James
James

Reputation: 82096

If you have no intention of using the fruit object when it's returned then I would simply return the weight directly rather than the fruit object. The factory method name actually does say it returns the weight, not the object, so in theory it's the correct approach i.e.

const float AppleWeight = 10;
const float BananaWeight = 10.4;
...
public static float GetFruitWeight(FruitList fruitType)
{
    switch (fruitType)
    {
        case FruitsList.Apple:
            return AppleWeight;
        case FruitsList.Banana:
            return BananaWeight;
        default:
            return 0;
    }
}

However, if you do intend to use the fruit object then I would rename your method to GetFruit, return IFruits (don't box) and call ReturnFruitWeight on the fruit instance for the weight.

Am I really following Factory pattern in this implementation?

The point of the factory pattern is to allow you to create objects without knowing the concrete type, so yes what you have here is a fairly basic example of the factory method pattern.

some materials in the internet uses an abstract class too ? What should I follow ? A interface implementation or should I use an abstract class and override it ?

This is all dependant on your application design. For example, I personally would only introduce an abstract base class if:

  • There was common code I could share across the classes
  • I needed some way of determining that a particular class belonged to a family of a particular type i.e. Banana is a type of Fruit.

Other than that, I would probably almost always go for an interfaced type approach. Bare in mind, you can have both, there's no reason why you couldn't have an abstract base class which supports a particular interface...

Upvotes: 5

ken2k
ken2k

Reputation: 48975

Do not return an object, but a IFruits. Also, rename your static method as it returns fruits, not their weight:

private static IFruits GetFruit(FruitsList fruitNumber)
{
    switch (fruitNumber)
    {
        case FruitsList.Banana:
            return new Banana();
        case FruitsList.Apple:
            return new Apple();
    }

    return null;  // Maybe you can throw a ArgumentException here
}
...
var theFruit = GetFruit(fruits);
var weight = theFruit.ReturnFruitWeight();

For the abstract class vs interface, both options are valid. If you do not want to provide default implementation for your methods, then the interface might be better as you can implement multiple interfaces but you can't inherit from multiple classes.

Upvotes: 1

Related Questions