如果我们使用工厂模式,我们应该对用户隐藏产品吗?

If we are using Factory Pattern should we hide products from user?

假设我有一个 AnimalFactory class,它产生 Dog, CatFish。 使用 AnimalFactory 使事情变得异常简单,一切都很好。

我的问题是,是否有规则或良好做法 建议我们隐藏 Dog、Cat 和 Fish,以免被直接使用?我的意思是 Dog myDog = new Dog(); 将在代码中被禁止。

如果有,如何正确隐藏?

是的,如果你的对象应该只通过工厂创建,你应该尽量避免有人跳过这条规则的可能性。

在 c# 中,如果 Dog、Cat 和 Fish 的消费者在不同的程序集上,您可以将构造函数设为内部,这样只有与 "animals" 在同一程序集中实现的工厂可以创建它们。

我确定 java 中有类似的内容。

这完全取决于消费者是否需要关心狗或猫,或者他们是否只关心一些动物?

也就是说,如果 Animal.Speak() 没问题,那么只暴露动物,让消费者不知道实现细节。但是,如果有 Dog 特有的东西,例如 Dog.BarkAtMoon(),那么您必须了解它的使用方式。

此外,您可能喜欢依赖接口,例如 IAnimal。然后你有 class Dog : IAnimal 和你的工厂 returns IAnimals。通过这种方式,消费者对实现的了解更少,并且只有界面。

也许你会有

class AnimalFactory
{
  IAnimal GetAnimal(AnimalTypeEnum type) { ... return IAnimal type requested ... }
  Dog GetDog(string name) { ... just give me a dog named "name" (or IDog) ... }
}

除了指出接口方面的其他答案外,如果需要以某种方式构造复杂对象,并且您想在一个地方(即工厂)强制执行该要求,工厂模式也很有用。在这种情况下,根据您的问题,最好还保护任何其他构造该对象的方法。

回答你的问题,是的。请允许我详细说明 -

当我们像Dog myDog = new Dog();这样直接实例化对象时,我们编写了一个依赖项。

现在假设,您希望为实例化 Dog 的函数编写单元测试用例,您将没有机会用模拟 Dog 对象替换实际的狗对象。因此,我们坚持使用接口并从外部提供依赖项。

如果我想强制使用接口并阻止使用 new 运算符,我可以进行以下设置 -

  1. 接口程序集 - 这将定义 public interface IDog

  2. 用于具体实现的程序集 - 这是有 internal class Dog 和一个 public class FactoryCreate 函数将 return IDog

  3. 客户端程序集 - 这里 Dog 将不可访问,因此客户端创建 dog 实例的唯一方法是通过工厂 return IDog 像这样 IDog dog = factory.Create();

为了传达我的观点,我将设置保持得非常简单

依赖倒置原则告诉我们客户端classes应该避免依赖具体的实现。工厂模式通过将客户端与创建逻辑屏蔽开来促进了这一点,并且客户端将使用一个接口而不是一些具体的 class。使具体 classes 包的构造函数成为本地而不是 public 可能是一种好方法。