【问题标题】:What is the difference between Factory and Strategy patterns?工厂模式和策略模式有什么区别?
【发布时间】:2010-10-11 15:14:27
【问题描述】:

谁能解释工厂模式和策略模式之间的区别?

对我来说,除了一个额外的工厂类(在工厂模式中创建产品对象)之外,两者看起来都一样

【问题讨论】:

标签: java design-patterns factory-pattern strategy-pattern abstract-factory


【解决方案1】:

工厂模式是一种创造模式。策略模式是一种操作模式。换句话说,工厂模式用于创建特定类型的对象。策略模式用于以特定方式执行操作(或操作集)。在经典示例中,工厂可能会创建不同类型的动物:狗、猫、老虎,而策略模式将执行特定动作,例如移动;使用跑步、步行或 Lope 策略。

其实两者可以一起使用。例如,您可能有一个创建业务对象的工厂。它可能会根据持久性介质使用不同的策略。如果您的数据以 XML 格式存储在本地,它将使用一种策略。如果数据在不同的数据库中是远程的,它将使用另一个。

【讨论】:

  • ` 策略模式用于以特定方式执行一个操作(或一组操作)` 是否意味着对对象的操作?
【解决方案2】:

策略模式允许你多态地改变一个类的行为。

工厂模式允许您封装对象创建。

加里提出了一个很好的观点。如果您将编码原则用于抽象而不是“具体化”,那么许多模式开始看起来像是主题的变体。

【讨论】:

    【解决方案3】:

    只是补充一下 tvanfosson 所说的,就实现而言,许多模式看起来都是一样的。也就是说,很多时候你创建了一个接口,而你的代码中可能以前没有一个接口,然后创建了一堆该接口的实现。区别在于它们的用途和使用方式。

    【讨论】:

      【解决方案4】:

      首先必须区分简单工厂和抽象工厂。第一个是一个简单的工厂,您只有一个类充当创建对象的工厂,而在后者中,您连接到工厂接口(定义方法名称),然后调用实现此接口的不同工厂应该基于某些标准具有相同方法的不同实现。例如,我们有一个 ButtonCreationFactory 接口,它由两个工厂实现,第一个 WindowsButtonCreationFactory(创建具有 Windows 外观的按钮)和第二个 LinuxButtonCreationFactory(创建具有 Linux 外观的按钮)。因此,这两个工厂确实具有相同的创建方法和不同的实现(算法)。您可以根据您想要的按钮类型在运行时引用它。

      例如,如果您想要具有 Linux 外观的按钮:

      ButtonCreationFactory myFactory = new LinuxButtonCreationFactory();
      Button button1 = myFactory.createButton(...);
      

      或者如果你想要 Windows 按钮

      ButtonCreationFactory myFactory = new WindowsButtonCreationFactory();
      Button button1 = myFactory.createButton(...);
      

      正是在这种情况下,它产生了一种策略模式,因为它区分了进行某些创建的算法。但是,它在语义上与它不同,因为它用于创建对象而不是操作算法。因此,基本上使用抽象工厂,您可以使用不同的策略创建对象,这与策略模式非常相似。然而,AbstractFactory 是创建性的,而 Strategy 模式是可操作的。在实施方面,它们的结果是相同的。

      【讨论】:

        【解决方案5】:

        Factory(以及 Factory 返回的 FactoryMethod)

        1. 创作模式
        2. 基于继承
        3. Factory 返回一个工厂方法(接口),该方法又返回具体对象
        4. 您可以用新的具体对象替换接口,客户端(调用者)不应该知道所有具体实现
        5. 客户端始终只访问接口,您可以在工厂方法中隐藏对象创建细节

        看看这个wikipedia articlejavarevisited article

        策略模式:

        1. 这是一种行为模式
        2. 它基于委托
        3. 它通过修改方法行为来改变对象的内部结构
        4. 用于在算法族之间切换
        5. 它在运行时改变对象的行为

        例子:

        您可以为特定项目(机票或购物车项目)配置折扣策略。在此示例中,您将在 7 月至 12 月期间为某件商品提供 25% 的折扣,而在 1 月至 6 月期间为该商品提供 25% 的折扣。

        相关帖子:

        Real World Example of the Strategy Pattern

        Design Patterns: Factory vs Factory method vs Abstract Factory

        【讨论】:

          【解决方案6】:
          • 工厂(方法)模式。

          仅创建具体实例。不同的论点可能导致不同的对象。这取决于逻辑等。

          • 策略模式。

          封装算法(步骤)来执行一个动作。因此,您可以更改策略并使用另一种算法。

          虽然两者看起来非常相似,但目的却大不相同,一个目的是创造另一个目的是执行一个动作。

          所以。如果你的工厂方法是固定的,你可能会这样:

           public Command getCommand( int operatingSystem ) { 
                switch( operatingSystem ) { 
                     case UNIX    :
                     case LINUX   : return new UnixCommand();
                     case WINDOWS : return new WindowsCommand();
                     case OSX     : return new OSXCommand();
                 }
            }
          

          但假设您的工厂需要更高级或动态的创建。您可以在工厂方法中添加策略并更改它而无需重新编译,该策略可能会在运行时更改。

          【讨论】:

          • 我不认为你在这里提出了正确的观点。首先,这些模式的原因之一是避免使用有利于多态性的条件。首先必须区分简单工厂和抽象工厂。d 第一个是简单工厂,其中只有一个类作为对象创建的工厂,而在后者中,您连接到接口然后调用根据某些标准,实现此接口的不同工厂应该具有相同方法的不同实现。 (继续)
          • 正是在这种情况下,它产生了一种策略模式,但它在语义上与它不同,因为它用于对象创建而不是操作。因此,基本上您可以使用不同的策略创建对象。
          • @OscarRyz 你能用一个描述两者的程序更新你的答案吗
          【解决方案7】:

          扩展 Oscar 所说的内容并参考他的代码:

          getCommand 是工厂,UnixCommand、WindowsCommand 和 OSXCommand 类是策略

          【讨论】:

            【解决方案8】:

            简单来说,策略模式更多的是在运行时创建行为,而您不关心实现类。另一方面,工厂是具体类实例的运行时创建,您可以使用已实现接口公开的任何行为(方法)。

            【讨论】:

              【解决方案9】:

              工厂模式是一种创建模式,它是用指定的属性(行为)创建的。在创建后的运行时,您不能更改它的属性(行为)。因此,如果您需要不同的属性(行为),您必须删除对象并创建具有所需属性(行为)的新对象。这不是 gud。 而在策略模式的情况下,您可以在运行时更改属性(行为)。

              【讨论】:

                【解决方案10】:

                您无法仅通过查看代码或分类来了解差异。要正确掌握 GoF 模式,请寻找它们的意图:

                策略:“定义一系列算法,封装每个算法,并使它们可互换。策略让算法独立于使用它的客户而变化。”

                工厂方法:“定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法让一个类将实例化推迟到子类。”

                下面是关于这两种模式的意图和区别的详细解释:Difference between Factory Method and Strategy design patterns

                【讨论】:

                  【解决方案11】:

                  我可能离题了,因为他的工厂实现示例非常紧密耦合且非常封闭,难怪您选择的是策略模式。工厂实现不应依赖于任何固定数量的被实例化的特定类,例如:

                  public Command getCommand( int operatingSystem ) {        
                     return commandTable.get(operatingSystem); 
                  }
                  
                  ...
                  
                  public class WindowsCommand implements Command {
                      ...
                      static {
                          CommandTable.getInstance().registerCommand(WIN_COMMAND_ID, new WindowsCommand());
                      }
                  
                  }
                  

                  我想选择一个或另一个的最合适的标准主要是你用来命名你的类和方法的术语,考虑到我们都应该倾向于对接口而不是类进行编程,并且还应该关注目标:我们旨在确定哪些代码将在运行时执行。也就是说,我们可以通过使用这两种模式中的任何一种来实现目标。

                  【讨论】:

                    【解决方案12】:

                    战略和工厂是不同的目的。在策略中,您定义了方法,使用此模式您可以交换行为(算法)。来到工厂,周围有很多变化。但是 GO4 的原始模式声明工厂将对象的创建留给子类。在这里,您将替换完整的实例而不是您感兴趣的行为。通过这种方式,您将替换完整的系统而不是算法。

                    【讨论】:

                      【解决方案13】:

                      简而言之:

                      Factory 用于创建具有相同行为的多个对象,但Strategy 用于创建具有不同工作方式的一个对象。

                      【讨论】:

                        【解决方案14】:

                        Factory PatternStrategy Pattern 之间的主要区别在于操作的完成位置。 Factory Pattern 对创建的对象进行操作(工厂类在创建后完成工作),而Strategy Pattern 对上下文类本身进行操作。

                        要将Factory Pattern更改为Strategy Pattern,而不是从工厂类返回创建的对象,将对象保存在上下文类中,并在上下文类中创建包装器方法来执行操作而不是执行直接从创建的对象进行操作。

                        虽然有人可能会问我们是否可以对创建的对象进行操作,但为什么我们仍然需要在上下文类中创建一个包装器呢?好的,关键是操作。 Strategy Pattern可以根据策略改变操作,不需要改变对象,可以依赖上下文对象做不同的操作,而不用改变对象本身。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2010-10-02
                          • 1970-01-01
                          • 2010-10-14
                          • 2015-12-28
                          • 2010-12-12
                          • 1970-01-01
                          相关资源
                          最近更新 更多