开发者

Strategy Design Pattern and Factory Method Design Pattern

I start learning Design Patterns. Now I understand a little bit b开发者_C百科ut there are quite a lot of confusions for me. What's the difference between Strategy DP and Factory Method DP? For me they both looks like the same.


Strategy is about behavior. Factory is about creation/instatation.

Suppose you have an algorithm, to calculate a discount percentage. You can have 2 implementations of that algorithm; one for regular customers, and one for extra-ordinary good customers.
You can use a strategy DP for this implementation: you create an interface, and 2 classes that implement that interface. In one class, you implement the regular discount-calculation algorithm, in the other class you implement the 'good customers' algorithm.

Then, you can use a factory pattern to instantiate the class that you want. The factory method thus instantiates either the regular customer-discount algorithm, or the other implementation.

In short: the factory method instantiates the correct class; the strategy implementation contains the algorithm that must be executed.


Strategies incapsulate different behaviors behind the same interface. You instantiate Strategies with new operator. For example (the same business case as Frederik suggested):

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

Factory Method incapsulates instantiation mechanism of some other interface (maybe a Strategy, but maybe something else). For example:

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

Strategy pattern is often used together with Factory Method, while Factory Method is often used for instantiation of other stereotypes, not only Strategies.


The difference is in their intention:

The factory method pattern is a creational pattern used to defer object instantiation to subclasses. On the other end, strategy pattern is a behavioral pattern used to decouple an algorithm from client code.

You would use the first if you need to abstract object creation by defining a method that returns an instance of a specific type, but letting subclasses implement it. In Java, an example would be as follows:

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...
}

Note how actual object instantiation is differed to the implementation by SomeAbstractClass.

On the other hand you would use the Strategy pattern if you need to decouple an algorithm from the calling code. This is similar to how the View communicates with the Controller in the MVC pattern. In a hypothetical java MVC UI kit this could be as follows:

// 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);
  }
}

Now, say you had another component that instead of clicking responded sliding (i.e. slider)

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);
  }
}

Note how in Button and Slider classes (Views) the logic of executing an action is exactly the same (both defer to the ActionHandler). We could therefore pull them to the parent class (Widget) and let subclasses just define the action handler implementation, like so:

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());
  }
}

By using the strategy pattern we can change our widget's behavior simply by configuring them with another concrete implementation of ActionHandler. In that way, widgets (views) are loosely coupled form action handling logic (controllers).

We could make things a little more interesting by mixing the strategy and the factory method pattern together, like so:

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();
   }
}

Please Note that this is an illustrative example of a strategy pattern and NOT how Swing (Java's default UI kit) is implemented.

Both patterns are somewhat similar in that they defer some piece of logic to somewhere else. This is a common theme in design patterns that enables the separation of concerns. However, the nature or intention of the deferred logic is completely different. Factory method defers creation logic to subclasses (in my example, the creation of concrete ActionHandler instances), whereas strategy pattern the execution of an algorithm (in my example, what to do when an the user interacts with a specific component).


You can find another java implementation for strategy pattern at http://javabyranjith.blogspot.in/2017/04/strategy-design-pattern.html

and

factory method design pattern at http://javabyranjith.blogspot.in/2014/06/factory-method-design-pattern.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜