What is the difference between Strategy pattern and Dependency Injection?

后端 未结 9 1730
长情又很酷
长情又很酷 2020-12-04 06:13

Strategy pattern and Dependency Injection both allow us to set / inject objects at run time. What is the difference between Strategy pattern and Dependency Injection?

相关标签:
9条回答
  • 2020-12-04 06:37

    Strategies are higher-level things that are used to change how things are computed. With dependency injection, you can change not just how things are computed but also change what is there.

    For me, it becomes clear when using unit tests. For production code execution, you have all the data hidden (i.e. private or protected); whereas, with unit tests, most of the data is public so I can look at it with the Asserts.


    Example of strategy:

    public class Cosine {
      private CalcStrategy strat;
    
      // Constructor - strategy passed in as a type of DI
      public Cosine(CalcStrategy s) {
        strat = s;
      }
    }
    
    public abstract class CalcStrategy {
      public double goFigure(double angle);
    }
    
    public class RadianStrategy extends CalcStrategy {
      public double goFigure(double angle) {
        return (...);
      }
    }
    public class DegreeStrategy extends CalcStrategy {
      public double goFigure(double angle) {
        return (...);
      }
    }
    

    Notice that there is no public data that is different between the strategies. Nor is there any different methods. Both strategies share all the same functions and signatures.


    Now for the dependency injection:

    public class Cosine {
      private Calc strat;
    
      // Constructor - Dependency Injection.
      public Cosine(Calc s) {
        strat = s;
      }
    }
    
    public class Calc {
      private int numPasses = 0;
      private double total = 0;
      private double intermediate = 0;
    
      public double goFigure(double angle) {
        return(...);
    }
    
    public class CalcTestDouble extends Calc {
      // NOTICE THE PUBLIC DATA.
      public int numPasses = 0;
      public double total = 0;
      public double intermediate = 0;
      public double goFigure(double angle) {
        return (...);
      }
    }
    

    Use:

    public CosineTest {
    
      @Test
      public void testGoFigure() {
        // Setup
        CalcTestDouble calc = new CalcTestDouble();
        Cosine instance = new Cosine(calc);
    
        // Exercise
        double actualAnswer = instance.goFigure(0.0);
    
        // Verify
        double tolerance = ...;
        double expectedAnswer = ...;
        assertEquals("GoFigure didn't work!", expectedAnswer,
             actualAnswer, tolerance);
    
        int expectedNumPasses = ...;
        assertEquals("GoFigure had wrong number passes!",
            expectedNumPasses, calc.numPasses);
    
        double expectedIntermediate = ...;
        assertEquals("GoFigure had wrong intermediate values!",
            expectedIntermediate, calc.intermediate, tolerance);
      }
    }
    

    Notice the last 2 checks. They used the public data in the test double that was injected into the class under test. I couldn't do this with production code because of the data hiding principle. I didn't want to have special purpose testing code inserted in the production code. The public data had to be in a different class.

    The test double was injected. That is different than just a strategy since it affected data and not just functions.

    0 讨论(0)
  • 2020-12-04 06:40

    Actually, dependency injection also looks very similar to the Bridge pattern. To me (and according to the definition), the Bridge pattern is to accommodate different versions of the implementation, while the Strategy pattern is for the totally different logic. But the sample code looks like it's using DI. So maybe DI is just a technic or implementation?

    0 讨论(0)
  • 2020-12-04 06:46

    Strategy is an arena to use your dependency injection skills. Real ways to implement dependency injection are as follows:-

    1. Events
    2. Configuration files of unity/structure map(or programmatically) etc.
    3. Extension Methods
    4. Abstract Factory pattern
    5. Inversion of control pattern(used by both strategy and Abstract Factory)

    There is one thing though that makes strategy stands apart. As you know in Unity when the application starts up all dependencies are set and we can't change it further. But strategy supports runtime dependency change. But WE have to manage/inject the dependency, not the responsibility of Strategy!

    Actually strategy does not talk about dependency injection. If needed it can be done through Abstract Factory inside a Strategy pattern. Strategy only talks about creating a family of classes with interface and 'playing' with it. While playing, if we find the classes are in a different tier then we have to inject it ourselves but not the job of Strategy.

    0 讨论(0)
提交回复
热议问题