Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 转换多个';否则';以更干净的方式发言_Java_Design Patterns - Fatal编程技术网

Java 转换多个';否则';以更干净的方式发言

Java 转换多个';否则';以更干净的方式发言,java,design-patterns,Java,Design Patterns,这里我的代码检测mimeType是否等于某个类型,如果等于,它将进行某种转换 public void convertToMp3(File src, File target,String mimeType){ if(mimeType.equals("audio/mpeg")){ ... }else if(mimeType.equals("audio/wav")){ mp3ToWav(); }else if(mimeType.equals("a

这里我的代码检测
mimeType
是否等于某个类型,如果等于,它将进行某种转换

public void convertToMp3(File src, File target,String mimeType){
    if(mimeType.equals("audio/mpeg")){
        ...
    }else if(mimeType.equals("audio/wav")){
        mp3ToWav();
    }else if(mimeType.equals("audio/ogg")){
        ...
    }else if(...){
    ... //More if and else here
}

我缩短了我的代码,因为它有很多else-if语句,什么设计模式适合删除许多if-and-else或else-if语句?

如果您使用的是
JDK 7
,您可以使用
switch-case
构造:

见:


对于以前的版本,
if-else
是唯一的选择。

如果对每种情况运行相同的方法,您应该检查您可能有一个
转换器
接口。然后可以为每个Mimetype创建一个类,如下所示:

public interface Converter {

    public void convertToMp3();
    public void convertToOgg();

}

public class MpegConverter implements Converter {

    public void convertToMp3() {
        //Code here
    }

    public void convertToOgg() {
        //Code here
    }

}
每个转换器都需要这样的类。然后,您可以设置如下地图:

Map<String, Converter> mimeTypeMap = new HashMap<String, Converter>();

mimeTypeMap.put("audio/mpeg", new MpegConverter());
Converter converter = mimeTypeMap.get(mimeType);
converter.convertToMp3();
使用这种方法,您可以在将来轻松添加不同的转换器


所有未经测试的,可能不会编译,但您得到的想法是

如果您使用pre-JDK7,您可以为所有类型添加枚举:


看看如何将字符串转换为枚举的堆栈溢出问题。

如果您不使用Java 7,您可以创建一个
enum
,并将该值与
开关一起使用。然后只需要传递枚举值(而不是文件,我不知道为什么要这样做)。它看起来也会更整洁

这些应该有助于您想做的事情:

 [Java Enum Examples][1] - 
 [Java Switch Case examples][2]

考虑使用策略设计模式和
映射
来分配适当的策略。如果您需要额外的功能,除了转换特定的
mimeType
,或者转换器是大型复杂的代码,并且您希望将每个转换器放在自己的
.java
文件中,则此功能尤其有用

 interface Convertor {
    void convert(File src, File target);
 }

 private static void convertWav(File src, File target) {
    ...
 }

 ...

 private static final Map< String, Convertor > convertors = new ...;
 static {
    convertors.put("audio/wav", new Convertor {
       void convert(File src, File target) {
          convertWav(src, target);
       }
    });
    convertors.put("audio/ogg", new Convertor {
       void convert(File src, File target) {
          convertOgg(src, target);
       }
    });
    ...
 }

 public void convertToMp3(File src, File target, String mimeType){
     final Convertor convertor = convertors.get(mimeType);
     if (convertor == null ) {
        ...
     } else {
        convertor.convert(src, target);
     }
 }
接口转换器{
无效转换(文件src、文件目标);
}
私有静态void convertWav(文件src,文件目标){
...
}
...
私有静态最终映射<字符串,转换器>转换器=新。。。;
静止的{
转换器。输入(“音频/wav”,新转换器{
无效转换(文件src、文件目标){
convertWav(src,目标);
}
});
转换器。put(“音频/ogg”),新转换器{
无效转换(文件src、文件目标){
convertOgg(src,target);
}
});
...
}
public void convertToMp3(文件src、文件目标、字符串mimeType){
最终转换器Convertor=convertors.get(mimeType);
if(转换器==null){
...
}否则{
convertor.convert(src,target);
}
}

这绝对是一种策略设计模式。但是你的总体设计有一个大问题。使用字符串来标识类型不是一个好的编程习惯。这仅仅是因为它很容易编辑,而且你可能会犯语法错误,花整个下午寻找编程错误。你可以避免使用地图

我建议如下:

  • 扩展类文件。新类向类文件中添加了一个新属性FileType和一个新方法convertTo(FileType)。此属性保留其类型:“音频”、“wav”。。。同样,不要使用字符串,请使用枚举。在本例中,我称之为FileType。扩展文件,如您所需:WavFile,AudioFile
  • 使用策略dp创建转换器
  • 使用出厂dp初始化转换器
  • 由于每个文件都知道自己的类型和目标类型(使用convertTo()方法指定目标类型),因此它将调用工厂自动获取正确的转换器 这种设计是可扩展的,您可以根据需要添加任意多的文件类型和转换器。 你投票的答案有误导性!!!!

    编码和黑客有很大区别。

    枚举和开关如何?工厂设计模式不适合您的需要?@RomanC我为什么要使用工厂设计模式?您想简化代码删除许多if-else语句,我使用了工厂模式。允许多态性为您工作。if/else语句是否有问题?当然,它不是一个漂亮的、过度设计的OOP模式,但它简单易懂,易于维护。任何阅读它的人都能理解它,那么为什么要尝试将它转换为其他东西呢?我运行不同的方法。这里不需要状态模式,这不是对有限状态机建模,而是根据输入类型选择不同的转换策略,因此策略模式更合适。但是如果我有不同的转换器而不是ConvertingComp3呢?我也有Ogg和Wav的转换器。不过我觉得有点迷茫,如果我想添加Ogg转换器,您可以向接口添加其他方法。e、 g.convertToOgg()我更新了答案在本例中,MPEGConverter上使用convertToOgg方法将MPG转换为MP3,convertToOgg用于将MPG转换为OGG。因此,不,他们做的工作不同。可能与namingGood想法混淆,对我来说,这似乎是一个非常干净的解决方案。只是不要忘记检查是否确实存在处理程序,如果找不到处理程序,则给出错误消息。对于那些可能不知道的人,这称为。为什么不在枚举本身放置一个handle方法?然后是
    MimeTypes.valueOf(mimeType.handle()
    @SpaceTrucker:好建议,它会比我的想法更干净。事实上,这将是cowls想法的一个很好的实现,因为不需要使用不同的实现来处理映射。我不相信建议使用
    开关
    作为重构多个
    if else if
    的一种方式的响应得到了23票的支持。吼叫声当我想到什么样的开发人员时,这让我感到害怕。@Daniel嗯,我猜太多的开发人员认为“行数越少越好”,尽管新代码与旧代码有相同的缺点。@Daniel,你能更明确地表达你对这种方法的担忧吗?问题中提供的用例归结为“执行一个且仅执行一个代码”
     interface Convertor {
        void convert(File src, File target);
     }
    
     private static void convertWav(File src, File target) {
        ...
     }
    
     ...
    
     private static final Map< String, Convertor > convertors = new ...;
     static {
        convertors.put("audio/wav", new Convertor {
           void convert(File src, File target) {
              convertWav(src, target);
           }
        });
        convertors.put("audio/ogg", new Convertor {
           void convert(File src, File target) {
              convertOgg(src, target);
           }
        });
        ...
     }
    
     public void convertToMp3(File src, File target, String mimeType){
         final Convertor convertor = convertors.get(mimeType);
         if (convertor == null ) {
            ...
         } else {
            convertor.convert(src, target);
         }
     }