Strategy Design Pattern and Factory Method Design Pattern

后端 未结 4 729
后悔当初
后悔当初 2021-02-13 04:44

I start learning Design Patterns. Now I understand a little bit but there are quite a lot of confusions for me. What\'s the difference between Strategy DP and <

4条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-13 04:58

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

提交回复
热议问题