【问题标题】:Strategy Design Pattern and Factory Method Design Pattern策略设计模式和工厂方法设计模式
【发布时间】:2017-04-06 16:07:02
【问题描述】:

我开始学习设计模式。现在我明白了一点,但对我来说有很多困惑。 Strategy DPFactory Method DP有什么区别?对我来说,它们看起来都一样。

【问题讨论】:

  • 这是两种截然不同的模式。是什么让你觉得他们是一样的?你能说出一些相似之处吗?
  • @space >> 我不知道。但对我来说,他们都试图实现同样的目标。我是 DP 的新手!你能解释一下这些,它对其他人也有用!谢谢!!!
  • 我的评论旨在作为一个鼓舞人心的问题。有时,在这种情况下,写下模式之间的相似之处和不同之处就很有帮助。这有时可以帮助您自己找到解决方案。

标签: design-patterns


【解决方案1】:

战略是关于行为的。工厂是关于创造/恢复的。

假设您有一个算法来计算折扣百分比。您可以有该算法的 2 个实现;一个给老客户,一个给特别好的客户。
您可以为此实现使用策略 DP:您创建一个接口,以及实现该接口的 2 个类。在一个类中,您实现了常规折扣计算算法,在另一个类中,您实现了“好客户”算法。

然后,您可以使用工厂模式来实例化您想要的类。因此,工厂方法实例化了常规的客户折扣算法或其他实现。

简而言之:工厂方法实例化了正确的类;策略实现包含必须执行的算法。

【讨论】:

  • @Frederik 但是为什么我不能在策略模式中实现工厂(不同的算法是创建对象的不同方式)。
  • 模式描述了如何解决常见问题。策略描述了如何解决不同的计算方法。工厂描述了如何实例化某个接口的不同实现;工厂并不意味着定义创建同一对象的不同方式。我允许您抽象必须为某个接口实例化的具体实现。
【解决方案2】:

策略将不同的行为封装在同一个界面后面。您使用 new 运算符实例化策略。例如(与 Frederik 建议的相同业务案例):

DiscountCalculator calc = new GoogCustomerDiscountCalculator();
Integer discount = calc.calculate();

工厂方法封装了一些其他接口的实例化机制(可能是一个策略,但也可能是别的东西)。例如:

DiscountFactory factory = new DiscountFactory();
DiscountCalculator calc = factory.getDiscountCalculator();
Integer discount = calc.calculate();

策略模式通常与工厂方法一起使用,而工厂方法通常用于其他原型的实例化,而不仅仅是策略。

【讨论】:

【解决方案3】:

区别在于他们的意图

工厂方法模式是一种创造性的模式,用于将对象实例化推迟到子类。另一方面,策略模式是一种行为模式,用于将算法与客户端代码分离。

如果您需要通过定义一个返回特定类型实例的方法来抽象对象创建,您将使用第一个,但让子类实现它。在 Java 中,示例如下:

public interface SomeAbstractObject {
   // methods...
}

public abstract class SomeAbstractClass {
  public abstract SomeAbstractObject newSomeObject();
  // Other methods...
}

public class SomeConcreteClassA extends SomeAbstractClass {
  public SomeAbstractObject newSomeObject() {
    // assuming SomeConcreteObjectA extends from SomeAbstractObject
    return new SomeConcreteObjectA();
  }
  // Other methods...
}

public class SomeConcreteClassB extends SomeAbstractClass {
  public SomeAbstractObject newSomeObject() {
    // assuming SomeConcreteObjectB extends form SomeAbstractObject
    return new SomeConcreteObjectB();
  }
  // Other methods...
}

注意实际的对象实例化与 SomeAbstractClass 的实现有何不同。

另一方面,如果您需要将算法与调用代码分离,则可以使用策略模式。这类似于 MVC 模式中 View 与 Controller 的通信方式。在假设的 java MVC UI 工具包中,可能如下所示:

// interface abstracting the algorithm of a user interaction with your ui components.
public interface ActionHandler {
   public void handle(Action a);
}

// concrete implementation of button clicked algorithm.
public class ButtonClickedHandler implements ActionHandler {
   public void handle(Action a) {
      // do some fancy stuff...
   }
}

public class Button extends Widget {

   // ActionHandler abstracts the algorithm of performing an action.
  private ActionHandler handler = new ButtonClickedHandler();

  // Delegates to the action handler to perform the action.
  public void execute(Action a) {
    handler.handle(a);
  }
}

现在,假设您有另一个组件,而不是单击响应滑动(即滑块)

public class Slider extends Widget {

  // SliderMovedHandler extends ActionHandler
  private ActionHandler handler = new SliderMovedHandler()

  // Delegates to action handler to perform the action.
  public void execute(Action a) {
    handler.handle(a);
  }
}

请注意,在 Button 和 Slider 类(视图)中,执行动作的逻辑是完全相同的(都遵循 ActionHandler)。因此,我们可以将它们拉到父类(Widget)中,让子类只定义动作处理程序实现,如下所示:

public class Widget {
  private ActionHandler handler;

  public Widget(ActionHandler handler) {
    this.handler = handler;
  }

  public void execute(Action a) {
    handler.handle(a);
  }
}

// concrete widget implementations change their behavior by configuring
// different action handling strategies.

public class Button extends Widget {
  public Button() {
    super(new ButtonClickedHandler());
  }
}

public class Slider extends Widget {
  public Slider() {
    super(new SliderMovedHandler());
  }
}

通过使用策略模式,我们可以简单地通过使用 ActionHandler 的另一个具体实现来配置小部件的行为来改变小部件的行为。这样,小部件(视图)就是松散耦合的表单动作处理逻辑(控制器)。

我们可以通过将策略和工厂方法模式混合在一起让事情变得更有趣,如下所示:

public abstract class Widget {

  public void execute(Action a) {
    // action handling strategy is retrieved by a factory method
    ActionHandler handler = getActionHandler();
    handler.handle(a);
  }

  // factory method defers creation of action handling strategy to subclasses
  public abstract ActionHandler getActionHandler();
}

// factory method defines different action handling strategy for different subclass

public class Button extends Widget {
   public ActionHandler getActionHandler() {
     return new ButtonClickedHandler();
   }
}

public class Slider extends Widget {
   public ActionHandler getActionHandler() {
     return new SliderMovedHandler();
   }
}

请注意,这是一个策略模式的说明性示例,而不是 Swing(Java 的默认 UI 工具包)的实现方式。

这两种模式有些相似之处在于它们将某些逻辑推迟到其他地方。这是实现关注点分离的设计模式中的一个常见主题。但是,延迟逻辑的性质或意图是完全不同的。工厂方法将创建逻辑推迟到子类(在我的示例中,具体 ActionHandler 实例的创建),而策略模式则执行算法(在我的示例中,当用户与特定组件交互时要做什么)。

【讨论】:

    【解决方案4】:

    【讨论】: