Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
298 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...