【问题标题】:If we are using Factory Pattern should we hide products from user?如果我们使用工厂模式,我们应该对用户隐藏产品吗?
【发布时间】:2015-10-27 17:04:09
【问题描述】:

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

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

如果有,我们如何正确隐藏它们?

【问题讨论】:

  • Spring 的依赖注入可能对做这类事情很有用。
  • Java - 假设您的工厂和动物类在同一个包中,向动物构造函数添加 protected, no modifier 修饰符将禁止包外的任何东西实例化动物
  • 工厂存在的原因是为了对用户隐藏产品。这是一个称为信息隐藏的原则,它减少了对可能改变的事物的依赖。
  • @Chrizt0f 可能与 java 9 及其模块功能有关。还有 *.internal.* 包约定。

标签: java c# design-patterns factory-pattern


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    我确定在 java 中也有类似的东西。

    【讨论】:

    • 在 Java 中,您可以使用私有构造函数来避免显式构造。对于您的动物示例,您可以使用:private Dog() {}
    【解决方案3】:

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

    也就是说,如果 Animal.Speak() 没问题,那么只需公开动物并将实现细节留给消费者未知。但是,如果有特定于 Dog 的东西,例如 Dog.BarkAtMoon(),那么您必须了解它是如何使用的。

    此外,您可能希望依赖接口,例如 IAnimal。然后你有类 Dog : IAnimal,你的工厂返回 IAnimals。通过这种方式,消费者对实现知之甚少,只知道接口。

    也许你会有

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

    【讨论】:

      【解决方案4】:

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

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

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

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

      1. 接口组件 - 这将定义 public interface IDog

      2. 具体实施的程序集 - 这是有 internal class Dog 和一个 public class Factory,其 Create 函数将返回 IDog

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

      我保持设置非常简单只是为了传达我的观点

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-20
          • 1970-01-01
          • 1970-01-01
          • 2013-05-04
          • 2010-12-28
          • 2017-06-13
          • 2011-08-14
          • 1970-01-01
          相关资源
          最近更新 更多