【问题标题】:Factory and Builder patterns (mixing two or more patterns)Factory 和 Builder 模式(混合两种或多种模式)
【发布时间】:2012-06-19 10:00:23
【问题描述】:

我知道这个问题被问了很多次,看起来这个问题是重复的,但我试图理解 SO、Google、GoF 上的帖子,但没有找到适合我的答案...

我了解工厂方法和生成器之间的区别: 工厂方法 - 创建从特定基类派生的对象,将具体实现与客户端解耦

Builder 方法 - 隐藏客户端创建对象的复杂性

现在我看到了我在 Internet (Abstract Factory Design Pattern for Dependency Injection) 上找到的示例,它是关于抽象工厂的,但这对我的问题无关紧要。这只是我查看的众多文章之一

//Abstract Factory for Dependency Injection
//Factory interface
public interface Module1ServiceFactory {
 ComponentA getComponentA();
 ComponentB getComponentB();
}

//Concrete factory
public class Module1ServiceFactoryImpl {
 private Module1ServiceFactory instance;

 private Module1ServiceFactoryImpl() {}

 public static synchronized Module1ServiceFactory getInstance() {
  if (null == instance) {
   instance = new Module1ServiceFactoryImpl();
  }

return instance;
 }

*** SUBJECT METHOD ***
 public ComponentA getComponentA() {
  ComponentA componentA = new ComponentAImpl();
  ComponentB componentB = getComponentB();
  componentA.setComponentB(componentB);
  return componentA;
 }

 public ComponentB getComponentB() {
  return new ComponentBImpl();
 }
}

我在该示例中看到,ComponentA 是一种复杂类型,getComponentA() 方法用于构建它。

  1. 那么为什么这被称为工厂而不是建造者???或者这意味着 Module1ServiceFactoryImpl 实现了 Factory AND Builder 模式?
  2. 在软件架构设计中创建实现多个设计模式的类/对象是否正确(常用)?

对不起我的英语:)

【问题讨论】:

    标签: design-patterns architecture factory-pattern


    【解决方案1】:

    那么为什么这被称为工厂而不是建造者???或者这意味着 Module1ServiceFactoryImpl 实现 Factory AND Builder 模式?

    之所以叫工厂,是因为它是工厂,而且只有工厂

    *** SUBJECT METHOD ***
     public ComponentA getComponentA() {
      ComponentA componentA = new ComponentAImpl();
      ComponentB componentB = getComponentB();
      componentA.setComponentB(componentB);
      return componentA;
     }
    
     public ComponentB getComponentB() {
      return new ComponentBImpl();
     }
    

    我在这里没有看到建设者。当然,这不是最简单的方法,但如果引入构建器模式,它绝对不会那么复杂。这更像是 JavaBean 方式并在新创建的对象上使用 setter。 Builder模式要求在最后一步创建对象,使创建对象不可能处于ready-to-use和not-ready-yet之间的状态。

    创建类/对象是否正确(常用) 在软件架构中实现不止一种设计模式 设计?

    是的,它是正确的并且有时被使用。不是很常见,因为每种模式都会增加一些复杂性,而多种模式会增加多种复杂性 :) 但是,当然,您可以将 builder 与 factory 混合(builder 需要一些被分解的部分), facory 与 builder (工厂封装了创建对象的用法与建设者)。模式很好地协同工作。 MVC 是很好的示例:

    GoF(四人组)并不将 MVC 称为一种设计模式,而是将其视为“一组用于构建用户界面的类”。在他们看来,它实际上是其他三种经典设计模式的变体:观察者(Pub/Sub)、策略和复合模式。根据 MVC 在框架中的实现方式,它也可能使用工厂模式和装饰器模式。

    http://addyosmani.com/blog/understanding-mvc-and-mvp-for-javascript-and-backbone-developers/

    【讨论】:

      【解决方案2】:

      工厂模式基本上隐藏了实例化具体对象(与构造函数不同),而是强调创建对象的接口。

      相比之下,构建器模式通常有助于实现多步骤构建行为,其中某些步骤也可能是可选的。它强调将对象创建拆分为逻辑单元,而不是像构造函数(或工厂方法)那样一次语义地创建它。

      我希望以下示例可以更清楚地表达差异。

      public class ComponentABuilder {
        private ComponentB componentB;
        private ComponentC componentC;
      
        public ComponentABuilder BuildComponentB(ComponentB b) {
          this.componentB = b;
        }
      
        public ComponentABuilder BuildComponentC(ComponentC c) {
          // Added another ComponentC, since just building B would
          // be pointless
          this.componentC = c;
        }
      
        public ComponentA Build() {
          // Might also be implemented via setters or whatever, the
          // point is that build now returns an object that is fully
          // built according to the steps the consumer performed via
          // the builder's methods, whereas a Factory Method would
          // do all the stuff by theirself.
          return new ComponentA(this.componentB, this.componentC);
        }
      }
      
      // Consumer sticks together his very own ComponentA
      // in (usually) multiple steps
      ComponentA c = new ComponentABuilder()
        .BuildComponentB(new ComponentBImpl()) // step 1
        .BuildComponentB(new ComponentCImpl()) // step 2
        .Build();
      
      // Factory builds their ComponentA according to their
      // own internal application, and getInstance is exposed
      // as an "atomic" step to the consumer
      ComponentA c2 = new ComponentAFactory().getInstance();
      

      构建器示例是一个相当具体的案例,应用它是有意义的。但是,它也应该可用于不同的应用程序。

      【讨论】:

      • 感谢回答,但它仍然无法解释为什么我的示例中的 Module1ServiceFactoryImpl 不是“Builder”。如我所见, public ComponentA getComponentA() 与 MyBuilder.Build 完全相同(构建复杂对象)...
      • 恕我直言getComponentA 做不是建设者所做的。构建器向消费者公开多个步骤,而工厂可以执行但不公开它们。我会再考虑如何更清楚地表达我的观点并编辑我的帖子。
      • @AlexDn 请再看一下新示例,我对其进行了更改以更准确地反映您的问题。
      • 我明白你在说什么,但它又在我脑海中一团糟......你说“构建器向消费者公开了多个步骤......” - Module1ServiceFactory 做同样的事情(ComponentA getComponentA() , ComponentB getComponentA()),从另一边 Builder 应该“隐藏”复杂性,但是对于许多暴露的方法,它看起来更复杂。例如 Car:Factory 类可以创建汽车基础、引擎、车门、车轮……但只有 Builder 知道引擎在基础存在之前无法组装到汽车上……那么为什么 Builder 应该公开多个方法?跨度>
      • 我同意它经常更复杂。 首先,例如,Joshua Bloch 建议使用构建器而不是工厂(或构造器)来减少参数数量,请参阅drdobbs.com/jvm/208403883?pgno=2。 第二,您可以让不同的构建器实现决定使用哪些具体部分,而不是让消费者传递它们(就像我做的那样)。在这种情况下,您可以让不同的实现 what 组装(what 汽车零件),而基础构建器决定 如何 组装它们(例如,发动机前的汽车底座)。
      【解决方案3】:

      这只是我的两分钱:

      1. Module1ServiceFactoryImpl 似乎正在实现 singleton 模式,所有字段和构造函数都是私有的,并且 getInstance() 用于获取 self 的新实例。
      2. 如果 Module1ServiceFactoryImpl 实现了 Module1ServiceFactory,它可能是工厂模式。然后客户端代码可以使用 工厂实现如下。
      class Client {
          public static void main(String[] args) {
              Module1ServiceFactory factory = Module1ServiceFactoryImpl.getInstance();
              ComponentA compA = factory.getComponentA();
              compA.printComponentA();
      
              ComponentB compB = factory.getComponentB();
              compB.printComponentB();
          }
      }
      
      class Module1ServiceFactoryImpl implements Module1ServiceFactory {
          private static Module1ServiceFactory instance;
      
          private Module1ServiceFactoryImpl() {
          }
      
          public static synchronized Module1ServiceFactory getInstance() {
              if (null == instance) {
                  instance = new Module1ServiceFactoryImpl();
              }
      
              return instance;
          }
      
          public ComponentA getComponentA() {
              ComponentA componentA = new ComponentAImpl();
              ComponentB componentB = getComponentB();
              componentA.setComponentB(componentB);
              return componentA;
          }
      
          public ComponentB getComponentB() {
              return new ComponentBImpl();
          }
      }
      
      interface Module1ServiceFactory {
          ComponentA getComponentA();
      
          ComponentB getComponentB();
      }
      
      interface ComponentA {
          void setComponentB(ComponentB componentB);
      
          void printComponentA();
      }
      
      class ComponentAImpl implements ComponentA {
          ComponentB componentB;
      
          @Override
          public void setComponentB(ComponentB componentB) {
              this.componentB = componentB;
          }
      
          @Override
          public void printComponentA() {
              System.out.println("ComponentA");
          }
      }
      
      interface ComponentB {
          public void printComponentB();
      }
      
      class ComponentBImpl implements ComponentB {
          @Override
          public void printComponentB() {
              System.out.println("ComponentB");
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-28
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多