Design patterns - Strategy pattern with Java Example

What is Strategy Design pattern?

Strategy design pattern comes under behavioural design pattern. It is also known as Policy pattern. It defines a family of algorithms and encapsulates each algorithm. The algorithm can be interchanged without changing much code. It bury algorithm implementation details in derived classes. It favours composition over inheritance.

Derived classes could be implemented using the template design pattern (We will discuss about it later on).

Implementation

We will take example of Compressing files. For compressing files, we can either use zip or can use rar compression strategy. In Strategy Design pattern, we will have following classes and interface.

1. We will define our Strategy to compress files.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public interface CompressionStrategy {
     //Compression algorithm
     public void compressFiles(List<File> files) throws FileNotFoundException;
}

2. We will now create two concrete classes which define the compression Strategy. i.e. ZIP and RAR strategy to compress files.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;
public class ZipCompressionStrategy implements CompressionStrategy {
   @Override
    public void compressFiles(List<File> files) throws FileNotFoundException {
     //using ZIP approach

    }
}

package com.gauravbytes.strategy.client;
import java.io.File;
import java.util.List;
public class RarCompressionStrategy implements CompressionStrategy {
     @Override
     public void compressFiles(List<File> files) {
             //using RAR approach
    }
}

3. We need on context/utility which will actually interact with the actual strategies to get work done.

package com.gauravbytes.strategy.client;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class CompressionUtility {
     private CompressionStrategy strategy;
     
     //this can be set at runtime by the application preferences
     public void setCompressionStrategy(CompressionStrategy strategy) {
             this.strategy = strategy;
    } 

    public void createArchive(List<File> files) throws Exception, FileNotFoundException {
         if (files == null)
             throw new RuntimeException(new NullPointerException("ListFile is null"));

         strategy.compressFiles(files);
    }
}

4. Now, we require client which will use the context/utility and generate the compressed files
package strategy.client;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
          List<File> files = new ArrayList<File>();
          CompressionUtility fileCompressor = new CompressionUtility();
          boolean isZipTypeCompression = false;
          //we could assume context is already set by preferences
         CompressionStrategy strategy = isZipTypeCompression ? new ZipCompressionStrategy() : new RarCompressionStrategy();

        fileCompressor.setCompressionStrategy(strategy);
       //get a list of files
       try {
         fileCompressor.createArchive(files); 
       } 
       catch (Exception e) { }
   }
}

Important note

I would like to explain how composition is favoured in Strategy design pattern. In class CompressionUtility, we have reference to CompressionStrategy interface and in context/utility class, there is one setter method for compression strategy i.e. you can change the alogorithm at run-time in context class if required.

No comments :

Post a Comment