2014-01-07 4 views
6

Примеры ниже бесстыдно сорваны из java.dzone.com, и изменены в соответствии с моим потребностям:Комбинирование Стратегии в шаблон Java стратегии

Наш интерфейс:

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

} 

Client класса с основным методом

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. Две стратегии могут быть или не быть совместимыми (в этом порядке, например имеет смысл в Tar файл GZipped?)
  3. Создание третьего класса TARGZipStrategy в порядке, но если бы у нас было 10 стратегий, позволяющих каждому другому быть частью действительного метода XXXCombinedStrategy, у нас было бы ~ 35 разные классы.

Есть ли опрятный способ произвольного запуска нескольких стратегий последовательно в рамках этого шаблона? Например, если я хотел создать файл .tar.gzip в конце?

Что я пытаюсь сказать, есть ли аккуратный способ объединить две стратегии вместе в одну?

Я чувствую, что то, что я делаю, должно иметь некоторое опрятное решение, и я не хочу изобретать велосипед, и в то же время я не хочу становиться слишком зависимым от моделей.

+1

Вы имеете в виду «декоратор»? – nachokk

+3

Возможно, вы ищете шаблон декоратора или составной узор. –

+0

@JBНайти составную стратегию? – Pureferret

ответ

8

Вы можете создать 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)); 
    } 
} 
+2

Используя это, OP может объединить любое количество других стратегий – tucuxi

+1

Возможно, вы даже можете изменить это на список и разрешить использование n стратегий вместо 2? – user1781290

+0

'Arrays.asList()' не возвращает 'ArrayList', кроме того, если я хочу сделать' .zip.tar.7zip', как я могу это сделать? – nachokk

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

} 
3

Вы, наверное, ищете 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 CompressionStrategydecoratee; 

    /** 
    * @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; 
} 

}

Zip сжатия

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); 
+0

Я не понимаю, как это будет работать в моем случае? – Pureferret

+0

@Pureferret см. Редактирование, это более надежное решение, здесь вы добавляете функциональность, вы можете сделать это с помощью zip.tar.7zip.whatever, вы добавляете функциональность динамически. – nachokk

Смежные вопросы