Combining Strategies in a Java Strategy Pattern
design-patterns, java, strategy-pattern
Solution
You could create a `JoinedCompressionStrategy`
class JoinedCompressionStrategy implements CompressionStrategy {
private final CompressionStrategy s0;
private final CompressionStrategy s1;
public JoinedCompressionStrategy(CompressionStrategy s0, CompressionStrategy s1) {
this.s0 = s0;
this.s1 = s1;
}
public File compressFiles(ArrayList<File> files) {
File archive = s0.compressFiles(files);
return s1.compressFiles(Arrays.asList(archive));
}
}
Problem
Examples below are shamelessly ripped off of java.dzone.com, and modified to suit my needs: Our interface: ``` public interface CompressionStrategy { public void compressFiles(ArrayList<File> files); } ``` Our First Implementation ``` public class GZipCompressionStrategy implements CompressionStrategy { public File compressFiles(ArrayList<File> files) { //using GZIP approach return archive; } } ``` Our Second Implementation: ``` public class TarCompressionStrategy implements CompressionStrategy { public File compressFiles(ArrayList<File> files) { //using TAR approach return archive; } } ``` And this is the use given: ``` public class CompressionContext { private CompressionStrategy strategy; //this can be set at runtime by the application preferences public void setCompressionStrategy(CompressionStrategy strategy) { this.strategy = strategy; } //use the strategy public File createArchive(ArrayList<File> files) { strategy.compressFiles(files); } } ``` Client Class with Main method ``` public class Client { public static void main(String[] args) { CompressionContext ctx = new CompressionContext(); File archive; //we could assume context is already set by preferences ctx.setCompressionStrategy(new TarCompressionStrategy()); //get a list of files ... archive = ctx.createArchive(fileList); ctx. setCompressionStrategy(new GZipCompressionStrategy()); archive = ctx.createArchive(archive); } } ``` Which feels messy, because: - I'm having to reset the strategy each time - The Two strategies may or may not be compatible (in that order, e.g. does it make sense to Tar a GZipped file?) - Creating a third TARGZipStrategy class is ok in principle, but if we had 10 strategies allowing for every other one to be part of a valid XXXCombinedStrategy method, we'd have ~35 different classes. Is there a neat way to arbitrarily run multiple strategies sequentially within this pattern? For instance if I wanted to create a `.tar.gzip` file at the end? What I'm trying to say is there neat way to combine two strategies together into one? I feel like what I'm doing should have some neat solution and I don't want to reinvent the wheel, and at the same time I don't want to fall into being too reliant on patterns.