【问题标题】:Combining Strategies in a Java Strategy Pattern在 Java 策略模式中组合策略
【发布时间】:2014-01-07 13:24:43
【问题描述】:

以下示例无耻地抄袭java.dzone.com,并根据我的需要进行了修改:

我们的界面:

public interface CompressionStrategy
{
  public void compressFiles(ArrayList<File> files);
}

我们的第一个实现

public class GZipCompressionStrategy implements CompressionStrategy
{

   public File compressFiles(ArrayList<File> files)
   {
     //using GZIP approach
     return archive;
   }

}

我们的第二次实施:

public class TarCompressionStrategy implements CompressionStrategy
{

   public File compressFiles(ArrayList<File> files)
   {
     //using TAR approach
     return archive;
   }

}

这是给定的用途:

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);
   }

}

带有 Main 方法的客户端类

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);         
   }
}

感觉很乱,因为:

  1. 我每次都必须重新设置策略
  2. 这两种策略可能兼容也可能不兼容(按此顺序,例如,对 GZipped 文件进行 Tar 是否有意义?)
  3. 原则上,创建第三个 TARGZipStrategy 类是可以的,但如果我们有 10 个策略允许每隔一个策略成为有效 XXXCombinedStrategy 方法的一部分,我们将有大约 35 个不同的类。

是否有一种巧妙的方法可以在此模式中任意顺序运行多个策略?例如,如果我想在最后创建一个.tar.gzip 文件?

我想说的是有没有巧妙的方法将两种策略组合在一起?

我觉得我正在做的事情应该有一些巧妙的解决方案,我不想重新发明轮子,同时我也不想过于依赖模式。

【问题讨论】:

  • 你的意思是decorator
  • 您可能正在寻找装饰器模式或复合模式。
  • @JBNizet 复合策略?
  • @Pureferret:是的;如响应中显示的 JoinedCompressionStrategy 所示。

标签: java design-patterns strategy-pattern


【解决方案1】:

你可以创建一个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));
    }
}

【讨论】:

  • 使用这个,OP 可以将任意数量的其他策略链接在一起
  • 也许您甚至可以将其更改为列表并允许使用 n 个策略而不是 2 个?
  • Arrays.asList() 不返回ArrayList,如果我想做一个.zip.tar.7zip 我该怎么做?
  • @nachokk 我想你可以使用可变参数?你的方法变成:public JoinedCompressionStrategy(CompressionStrategy ... s),s 被当作一个数组。
  • @nachokk 也可以,如果您将压缩方法更改为 compressFiles(Files .. files) 并且需要 ArrayLists 和 Arrays。
【解决方案2】:

您可能正在寻找decorator pattern 的实现。此模式的目的是为对象动态添加额外的职责。权衡是你也会得到子类的爆炸式增长。

代码示例:

通用接口。

   public interface CompressionStrategy{
       File compressFiles(List<File> files);
   }

所有文件的基本压缩。

public class CompressionBase implements CompressionStrategy{

    @Override
    public File compressFiles(List<File> files)) {
        //return default compression
    }

}

装饰器抽象类

public abstract class AbstractCompressionDecorator implements CompressionStrategy{

    private final CompressionStrategy decoratee;

    /**
     * @param decoratee
     */
    public AbstractCompressionDecorator(CompressionStrategy decoratee) {
        super();
        this.decoratee = decoratee;
    }

    @Override
    public File compressFiles(List<File> files) {
        File file = decoratee.compressFiles(files); 
        return compressFilesToAnotherFormat(file);
    }

    protected abstract File compressFilesToAnotherFormat(File file);


}

和装饰器的具体类。

public class TarCompression extends AbstractCompressionDecorator {

    public TarCompression (CompressionStrategy compressionStrategy) {
            super(compressionStrategy);
    }

@Override
protected File compressFilesToAnotherFormat(File file) {
    // tar compression logic here;
}

}

压缩压缩

 public class ZipCompression extends AbstractCompressionDecorator {

    public ZipCompression (CompressionStrategy compressionStrategy) {
            super(compressionStrategy);
    }

@Override
protected File compressFilesToAnotherFormat(File file) {
    // zip compression logic here;
}

和一个简单的工厂来创建对象

public final class CompressionFactory {

    private CompressionFactory (){}

    public static CompressionStrategy create(String extension){

        CompressionStrategy compressionStrategy = new CompressionBase();        

            if(extension.contains("zip")){
               compressionStrategy = new ZipCompression(compressionStrategy);
            }else if(extension.contains("tar.gzip")){
               compressionStrategy = new TarCompression(new GzipCompression(compressionStrategy));
            }

        return compressionStrategy ;
    }
}

然后在客户端代码中你只需要写这个。

CompressionStrategy compressionStrategy = CompressionFactory.create("tar.gzip");
File file = compressionStrategy.compressFiles(files);

【讨论】:

  • @Pureferret 查看编辑,这是一个更强大的解决方案,您可以在此处添加功能,您可以使用zip.tar.7zip.whatever 来添加功能。
【解决方案3】:
public class TgzCompressionStrategy implements CompressionStrategy
{
     TarCompressionStrategy tar = new TarCompressionStrategy();
     ZipCompressionStrategy zip = new ZipCompressionStrategy();

    public File compressFiles(ArrayList<File> files)
    {
        File archive = tar.compressFiles(files);
        archive = zip.compressFiles(archive); // need to handle archive is not array list, but you can do that
        return archive;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    相关资源
    最近更新 更多