Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A Factory Pattern that will satisfy the Open/Closed Principle?

I have the following concrete Animal products: Dog and Cat.

I am using a parameterized Factory method to create said products. Depending on the AnimalInfo parameter that is passed to the Factory method, a concrete product will be created. The mapping logic is placed in the Factory method.

Here is my code:

 public abstract class AnimalInfo
    {
        public abstract String Sound { get; }
    }

    public class DogInfo : AnimalInfo
    {
        public override string Sound
        {
            get { return "Bark"; }
        }
    }

    public class CatInfo : AnimalInfo
    {
        public override string Sound
        {
            get { return "Meow"; }
        }
    }

    public abstract class Animal
    {
        public abstract void Talk();
    }

    public class Dog : Animal
    {
        private readonly DogInfo _info;

        public Dog(DogInfo aInfo)
        {
            _info = aInfo;
        }

        public override void Talk()
        {
            Console.WriteLine(_info.Sound);
        }
    }

    public class Cat : Animal
    {
        private readonly CatInfo _info;

        public Cat(CatInfo aInfo)
        {
            _info = aInfo;
        }

        public override void Talk()
        {
            Console.WriteLine(_info.Sound);
        }
    }

Here's my Factory method with its logic:

public static class AnimalFactory
{
    public static Animal CreateAnimal(AnimalInfo aInfo)
    {
        if (aInfo is DogInfo)
            return new Dog(aInfo as DogInfo);
        if (aInfo is CatInfo)
            return new Cat(aInfo as CatInfo);
        return null;
    }
}

The problem I'm seeing here is that the Factory method itself violates the Open/Closed principle in such a way that if I add a new Animal, I will need to modify the Factory method to reflect the new mapping.

Is there a way to make the creation more "dynamic" via reflection? More importantly, is there any anti-pattern in my design?

like image 410
Ian Avatar asked Oct 24 '11 13:10

Ian


People also ask

Which design pattern uses open-closed principle?

For example, the Decorator pattern offers us to follow the Open Close principle. Furthermore, we may use the Factory Method, Strategy pattern and the Observer pattern to design an application with minimum changes in the existing code.

Does Factory Pattern follow open-closed principle?

No, it doesn't violate the Open/Closed principle at all. Open/Closed means you can modify the way a system works without modifying the code that already exists.

What is open close principle with example?

The Open-Close principle (OCP) is the O in the well known SOLID acronym. A module will be said to be open if it is still available for extension. For example, it should be possible to add fields to the data structures it contains, or new elements to the set of functions it performs.

Which of the following is open-closed principle?

In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.


1 Answers

Let me sidestep a bit. The SOLID principles are good. But realize at some point, the principles break down, a fact even the originator of the SOLID term acknowledges. Yes, you want to follow single responsibility, open/closed, etc., but when you do so, something has to know how to create all those things that are otherwise nicely decoupled with single responsibilities.

Think about one of the things Uncle Bob said regarding ifs and switches in your code. "Have it exactly once." It stands to reason that the long if or the switch will indeed be a violation of SRP and OCP. And that's OK, if you have that violation once.

So go ahead, have your

if (a)
   return x;
else if (b)
   return y;
else if (c)
   return z;
else
   throw new InvalidOperationException();

And have it once. Yes, it's a violation of OCP. Yes, it might violate SRP. But something somewhere has to. The key is reducing the number of those somethings and those somewheres.

like image 163
Anthony Pegram Avatar answered Oct 10 '22 12:10

Anthony Pegram