views:

68

answers:

2

In a scenario like below where an object needs to be intantiated based on some conditional logic, can the factory method pattern help to avoid client code getting cluttered due to number of if/elseif conditions (which would also be a maintenance nightmare if more and more products needs to get created due to different variations of logics).

Or else is there a any other design pattern that could come to rescue?

public interface IProduct
{
    void Method1();
}

public class ProductA : IProduct
{
    void Method1()
    {
    }
}

public class ProductB : IProduct
{
    void Method1()
    {
    }
}

public class ProductC : IProduct
{
    void Method1()
    {
    }
}

public class Client
{
    public void Test()
    {
        int count = 5;

        IProduct product;

        if (count < 10)
        {
            product = new ProductA();
        }
        else if (count == 10)
        {
            product = new ProductB();
        }
        else if (count > 10)
        {
            product = new ProductC();
        }

        product.Method1();


    }
}
+3  A: 

It looks like the factory pattern is exactly what you want:


public class ProductFactory
{
    public IProduct GetProduct(int count)
    {
        if (count < 10)
        {
            return new ProductA();
        }
        else if (count == 10)
        {
            return new ProductB();
        }
        else if (count > 10)
        {
            return new ProductC();
        }
    }
}

Then wherever your client code needs an instance it can just go


public class Client
{
    public void Test()
    {
        ProductFactory factory = new ProductFactory();

        IProduct product = factory.GetProduct(5);

        product.Method1();
    }
}

Tom Carver
+1  A: 

I don't believe Mr. Carver's solution strictly follows the structure of the Factory Pattern described in the GOF Design Pattern book . However, it is a very common programming idiom (Simple Factory) and likely a good approach for this design.

The Factory Pattern calls for the Concrete Creator to be derived from a Creator. Typically, the Creator delegates the creation of the product to the Concrete Creator. This is useful when a new factory might be added in the future. For example, imagine if you created a new factory that could manufacture a the specific products with less resources (count is used as a proxy for "resource").

    public interface IProduct
    {
      void PerformService();
    }
    public class ProductA : IProduct
    {
      public void PerformService()
      {
        Console.WriteLine("Product A's service.");
      }
    }
    public class ProductB : IProduct
    {
      public void PerformService()
      {
        Console.WriteLine("Product B's service.");
      }
    }
    public class ProductC : IProduct
    {
      public void PerformService()
      {
        Console.WriteLine("Product C's service.");
      }
    }
    abstract class ProductFactory
    {
      public abstract IProduct CreateProduct(int count);
    }
    class OriginalFactory : ProductFactory
    {
      public override IProduct CreateProduct(int count)
      {
        if (count < 10)
        {
          return new ProductA();
        }
        else if (count == 10)
        {
          return new ProductB();
        }
        else if (count > 10)
        {
          return new ProductC();
        }
        else
        {
          return null;
        }
      }
    }
    class NewFactory : ProductFactory
    {
      public override IProduct CreateProduct(int count)
      {
        if (count < 20)
        {
          return new ProductA();
        }
        else if (count == 20)
        {
          return new ProductB();
        }
        else if (count > 20)
        {
          return new ProductC();
        }
        else
        {
          return null;
        }
      }
    }
    public class FactoryTest
    {
      public void TestNew()
      {
        ProductFactory factory = new NewFactory();
        IProduct product = factory.CreateProduct(10); // Product B
        product.PerformService();
      }
      public void TestOld()
      {
        ProductFactory factory = new OriginalFactory();
        IProduct product = factory.CreateProduct(10); // Product A
        product.PerformService();
      }
    }
hgilson