策略设计模式和工厂方法设计模式

15

我开始学习设计模式。现在我有点明白了,但是还有很多困惑。 策略模式工厂方法模式之间有什么区别?对我来说它们看起来都一样。


1
这是两种非常不同的模式。你为什么认为它们是相同的?你能说出一些相似之处吗? - Björn Pollex
@space >> 我不知道。但对我来说,它们都试图达到同样的目标。我是DP的新手!你能解释一些关于它们的内容吗?这对其他人也会有用!谢谢!!! - kevin
1
我的评论旨在激发问题。有时候,在这种情况下,写下模式之间的相似之处和不同之处有助于找到解决方案。这有时能够帮助你自己找到解决方案。 - Björn Pollex
4个回答

53

策略模式是关于行为的,工厂模式是关于创建/实例化的。

假设您有一个算法用于计算折扣百分比。您可以有两个实现该算法的版本:一个适用于普通客户,另一个适用于非常优秀的客户。
您可以使用策略设计模式来实现这个功能:创建一个接口和两个实现该接口的类。在一个类中,您实现了普通客户的折扣计算算法,在另一个类中,您实现了‘好客户’的算法。

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

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


@Frederik 但是为什么我不能在策略模式中实现工厂(不同的算法是创建对象的不同方式)呢? - Mahesh Jagtap
模式描述了如何解决常见问题。策略描述了如何以不同的方式计算某些东西。工厂描述了如何实例化某个特定接口的不同实现;工厂并不意味着定义创建相同对象的不同方法。它允许您抽象出必须为某个接口实例化的具体实现。 - Frederik Gheysels

11

策略模式通过相同的接口封装了不同的行为。您可以使用 new 操作符实例化策略。例如(与 Frederik 建议的相同业务案例):

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

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

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

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


给出的例子不是工厂方法。GoF工厂模式在这里描述:https://dev59.com/w2025IYBdhLWcg3w4qEx#50786084 - jaco0646

5

两种模式的区别在于它们的意图

工厂方法模式是一种创建型模式,用于将对象实例化延迟到子类。另一方面,策略模式是一种行为型模式,用于将算法与客户端代码解耦。

如果您需要通过定义返回特定类型实例的方法来抽象对象创建,并让子类实现它,则可以使用第一个。在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模式中与控制器通信的方式。在一个假设的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默认的用户界面工具包)的实现方式。
两种模式在某种程度上相似,因为它们将某些逻辑推迟到其他地方。这是设计模式中的一个常见主题,使关注点分离成为可能。然而,推迟的逻辑的本质或意图完全不同。工厂方法将创建逻辑推迟到子类(在我的示例中,是具体ActionHandler实例的创建),而策略模式则将算法的执行推迟到其他地方(在我的示例中,是当用户与特定组件交互时要执行什么操作)。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接