简体   繁体   中英

C# Factory Pattern newbie

I've been reading everything I can find about Factory/Abstract Factory/Simple Factory/etc. I've been unable to find an answer to this question. I understand the classes the factory creates must implement the same interface, or derive from the same base class. But what happens if the different classes don't end up with the same public interface? IE SubClass1 and SubClass2 both derive from BaseClass. Now SubClass1 adds PropertyA, and SubClass2 adds PropertyB. Am I correct in assuming these classes can't be created by a factory, since they don't have the same interface? Or, if they were created as BaseClass, they wouldn't expose their new properties. The same problem exists with a common interface. And if anyone knows an author that addresses this, I'd appreciate a reference.

Thanks so much!

I think you have missed the purpose of an interface. If you are using interfaces it may not be best practice to create classes the have public methods which are not part of an interface.

So if your factory produces IAnimal. You should not assume you are getting a Dog class that implements a WagTail method, or a Cat class that LandsOnFeet. You need to define IDog and ICat. (Possibly inheriting from IAnimal).

You then can consider how your factory behaves. You have a couple of options.

A. Generics

You could then create a Generic Factory interface IAnimalFactory which when implemented returns either an IAnimal or the specific type.

public interface IAnimal
    {
        int Legs();
    }

public interface IAnimalFactory<T> where T: IAnimal 
{
    IAnimal CreateAnimal();
    T CreateSpecificAnimal();
}

public interface IDog:IAnimal 
{
    void WagTail();
}

public interface ICat : IAnimal
{
    void LandOnFeet();
}

public class Dog:IDog
{
//Implementation Excluded
}

public class Cat : ICat
{
 //Implementation Excluded
}

public class DogFactory:IAnimalFactory<IDog>
{
    public IAnimal CreateAnimal()
    {
        return (IAnimal)CreateSpecificAnimal();
    }

    public IDog CreateSpecificAnimal()
    {
        return new Dog();
    }

}

public class CatFactory : IAnimalFactory<ICat>
{
    public IAnimal CreateAnimal()
    {
        return (IAnimal)CreateSpecificAnimal();
    }

    public ICat CreateSpecificAnimal()
    {
        return new Cat();
    }

}

The Generic approach gives you some future proofing if you then decide to implement IDomesticDog or IWildDog, and is my preference, but may be more complex then necessary depending on your needs.

B. Specific Methods per SubClass

You could also create a factory that has functions which create a dog or cat of type IAnimal.

public class AnimalFactory
    {
        public IAnimal GetDog()
        {
            return (IAnimal) new Dog();
        }

        public IAnimal GetCat()
        {
            return (IAnimal) new Cat();
        }

    }

Now as advised above you can safely cast to IDog or ICat.

I don't think there is one author that will specifically answer your question. However reading about Inversion of Control and Dependency Injection will likely give you the right level of information you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM