【问题标题】:C# Factory Pattern newbieC#工厂模式新手
【发布时间】:2015-03-31 12:57:24
【问题描述】:

我一直在阅读有关工厂/抽象工厂/简单工厂/等的所有信息。我一直无法找到这个问题的答案。我知道工厂创建的类必须实现相同的接口,或者从相同的基类派生。但是如果不同的类最终没有相同的公共接口会发生什么呢? IE。 SubClass1 和 SubClass2 都派生自 BaseClass。现在SubClass1 添加 PropertyA,SubClass2 添加PropertyB。我是否正确假设这些类不能由工厂创建,因为它们没有 相同的接口?或者,如果它们被创建为 BaseClass,它们就不会公开它们的新属性。公共接口也存在同样的问题。如果有人知道解决此问题的作者,我将不胜感激。

非常感谢!

【问题讨论】:

  • 它们仍然可以具有相同的界面。如果您通过界面访问它们,则看不到额外的属性
  • 同意伊万。这些类可以由工厂创建,但如果不进行强制转换,则不能使用扩展属性(方法)。你可以使用强制转换,但对我来说这看起来很糟糕
  • 我也同意 Ewan,Head First Design Patterns 也非常适合解释模式的细微差别,包括工厂:amazon.co.uk/Head-First-Design-Patterns-Freeman/dp/0596007124
  • 是的,他们可以有相同的界面,但我的问题是当他们有相同的界面时该怎么办。它们确实实现了相同的接口,但具有不包含在该接口中的公共方法,因此如果由工厂创建,则无法看到这些方法。
  • 我认为失望证实了我的怀疑。如果我使用工厂,我需要显式地转换返回的对象,这有点否定工厂的价值,除了马虎。我读过“Head First Design Patterns”(一本优秀的新手书顺便说一句),但同样,他们使用“最佳案例”场景。这对于它的书(介绍)来说非常棒。但我一直在寻找漏洞在哪里,所以我不会陷入其中。谢谢大家!

标签: c# factory-pattern


【解决方案1】:

我认为您错过了界面的目的。如果您使用接口,则创建具有不属于接口一部分的公共方法的类可能不是最佳做法。

因此,如果您的工厂生产 IAnimal。你不应该假设你得到了一个实现 WagTail 方法的 Dog 类,或者一个 LandsOnFeet 的 Cat 类。您需要定义 IDog 和 ICat。 (可能继承自 IAnimal)。

然后您可以考虑您的工厂的行为方式。你有几个选择。

A.泛型

然后您可以创建一个通用工厂接口 IAnimalFactory,该接口在实现时返回 IAnimal 或特定类型。

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();
    }

}

如果您决定实施 IDomesticDog 或 IWildDog,通用方法可为您提供一些未来的证明,这是我的偏好,但根据您的需要,可能会比必要的更复杂。

B.每个子类的具体方法

您还可以创建一个具有创建 IAnimal 类型的狗或猫的函数的工厂。

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

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

    }

现在按照上面的建议,您可以安全地转换为 IDog 或 ICat。

我认为没有一位作者会专门回答您的问题。然而,阅读控制反转和依赖注入可能会为您提供所需的正确信息。

【讨论】:

  • 我不同意你所说的“大多数类都应该实现一个接口”,除非类需要实现一个接口,否则这条规则只会导致很多无用的接口。
  • 公平评论@BradleyUffner 我已相应修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-13
相关资源
最近更新 更多