2

I was reading "Beginning Spring" and this particular paragraph caught my attention:

The DI pattern resembles other patterns such as Factory or Strategy. We can say that with the Factory pattern the instantiation of objects is still within the responsibility of the Factory definition, which is your code, but with the DI it’s externalized to another component/framework. On the other hand, with the Strategy pattern, the current implementation gets replaced with the help of multiple objects of a same interface, which contain that implementation inside. However, with the DI, the objects that contain those implementations are wired regardless of the implementation defined.

I am not sure if I understand what the author is saying in the emphasised part, but reading this made me realise, Strategy Pattern is an Inversion of Control implementation, isn 't it? (Q1)

So my second question (Q2) is: How is Strategy Pattern different compared to Dependency Injection?

  • 5
    Keep in mind that IoC exists on a different level than design patterns like Strategy, Factory, or whatever it may be. You can pretty much have DI combined with almost any pattern, or not use it at all and still use pretty much any pattern. They are completely orthogonal. – T. Sar Sep 8 '17 at 17:36
  • 1
    Can you provide a bit more text from that book? The disembodied quote you provided really doesn't make much sense without more context. – Robert Harvey Sep 8 '17 at 17:48
  • 2
    Your second question has already been adequately answered elsewhere. – Robert Harvey Sep 8 '17 at 17:56
3

The strategy pattern, simply put, is providing the ability to specify a concrete behavior for something so that its consumer can ignore what the concrete behavior is. An example is something like a logging strategy. The thing doing the logging doesn't care where the log messages go.

Dependency Injection is the idea that things are given their dependencies rather than seeking them out.

There's still scenarios where code would know how to build the strategy they want, or otherwise directly depend on the strategy implementations. They're uncommon and best avoided, but hopefully that helps distinguish the orthogonal concepts for you.

1

with the Strategy pattern, the current implementation gets replaced with the help of multiple objects of a same interface,

Is trying to say that if A knows how to use B because A knows the I interface that B implements then A can swap out B for C so long as C also implements I.

A--(I)-->B can be easily changed to A--(I)-->C

The strategy pattern is about being able to change from one to the other at run time.

However, with the DI, the objects that contain those implementations are wired regardless of the implementation defined.

Dependency Injection is about doing A--(I)-->B now expecting that eventually someone will need a feature that will make you create C.

1

From my PoV, the most useful way to look at the difference is:

Dependency Injection: Multiple ways to do conceptually the same thing (e.g. "storing an object" in Db A, Db B or FakeDb)

Strategy: Parameterize the function to have conceptually different functionality (e.g. SortAsc, SortDesc or SortByLastName)

0

Late to the party, but I wanted to give a 'refactoring' example to complement other peoples' answers.

I'm going to use the example of a class that decompresses a file:

public class FileDecompressor
{
   public void DecompressFile()
   {
      string filePath = "/path/to/file/file.gzip";
      if (filePath.EndsWith(".gzip"))
      {
         unzipGZipFile(filePath);
      }
   }
}

Dependency Injection (DI) is providing a dependency to an object, but doesn't require the dependency to be any particular shape. You might pass the dependency into the object as a constructor argument, attach it to a field or property, or pull it from a container object. In our example the decompress file method creates the filepath that it is dependent on, "/path/to/file/file.gzip". To let that dependency (the filepath) be set by the method consumer, we can make the dependency a method parameter, like so:

   public void DecompressFile(string filePath)
   {
      if (filePath.EndsWith(".gzip"))
      {
         unzipGZipFile(filePath);
      }
   }
...

...

So, that's DI - Moving the provision of dependencies to the consumer of a method or class.

The strategy pattern is a specific implementation of a generic behavior. In our example, we've hardcoded that we decompress .gzip files only. If we want to change just that portion of if, we could let the consumer insert a "DecompressionStrategy" that would dictate how to decompress the file.

Our final code could look something like this:

public class FileDecompressor
{
   IDecompressionStrategy DecompressionStrategy;

   public FileDecompressor(IDecompressionStrategy decompressionStrategy)
   {
      // This is the strategy object being DIed into the class.
      DecompressionStrategy = decompressionStrategy;      
   }

   public void DecompressFile(string filePath)
   {
      DecompressionStrategy.DecompressFile(filePath);
   }
}

Now you could use all of these as a consumer:

// Seeing both DI and strategy pattern in use
var gzipDecompressor = new FileDecompressor(GZipDecompressionStrategy); 
var 7zDecompressor = new FileDecompressor(7zDecompressionStrategy);
etc..

In this small example, it's harder to see the benefit, because the FileDecompressor class doesn't have any non-pass-through logic, but if you extend the FileDecompressor class to do something like take a path and filename, or add additional error-handling logic, it becomes easier to see the benefits of using the strategy pattern.

protected by gnat Apr 12 at 7:37

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.