Java中Switch Case的替代方案

Bij*_* CD 9 java conditional-statements

有没有其他方法可以在Java中实现一个switch case,而不是看起来不好看的else.根据选择相应的方法,必须执行一组值组合.

Osc*_*Ryz 29

如果您的代码周围有大量的开关/案例陈述,它们会让您发疯.

您可以选择重构:使用多态替换条件.

假设您有一个用于将信息保存到不同设备的软件:定义了4个持久性操作:获取,保存,删除,更新,这可以通过N个持久性机制实现(平面文件,网络,RDBMS, XML等).

您的代码必须全部支持它们,所以在4个不同的地方你有这个:

之前

class YourProblematicClass { 

....

     public void fetchData( Object criteria ) {

          switch ( this.persitanceType ) {
              case FilePersistance:
                  // open file
                  // read it
                  // find the criteria
                  // build the data
                  // close it.
                  break;
               case NetWorkPersistance: 
                   // Connect to the server
                   // Authenticate
                   // retrieve the data 
                   // build the data 
                   // close connection
                   break(); 
                case DataBasePersistace:
                   // Get a jdbc connection
                   // create the query
                   // execute the query
                   // fetch and build data
                   // close connection
                   break;
           }
           return data;
         }    
Run Code Online (Sandbox Code Playgroud)

保存/删除/更新也是如此

 public void saveData( Object data) {

      switch ( this.persitanceType ) {
          case FilePersistance:
              // open file, go to EOF, write etc.
              break;
           case NetWorkPersistance: 
               // Connect to the server
               // Authenticate
               // etc
               break(); 
            case DataBasePersistace:
               // Get a jdbc connection, query, execute...
               break;
       }
     }
Run Code Online (Sandbox Code Playgroud)

等等....

 public void deleteData( Object data) {

      switch ( this.persitanceType ) {
          case FilePersistance:
              break;
           case NetWorkPersistance: 
               break(); 
            case DataBasePersistace:
               break;
       }
  }

 public  void updateData( Object data) {

      switch ( this.persitanceType ) {
          case FilePersistance:
              break;
           case NetWorkPersistance: 
               break(); 
            case DataBasePersistace:
               break;
       }
  }
Run Code Online (Sandbox Code Playgroud)

使用switch/case语句会出现问题:

  • 每次要添加新类型时,都必须在每个部分中插入新的开关/案例.

  • 很多时候,有些类型是相似的,它们不需要不同的开关/外壳(你可以级联它们)

  • 他们是其他一些,有时他们略有不同
  • 您甚至可能需要在运行时加载不同的类型(如插件)

因此,这里的重构将是添加接口或抽象类型,并使不同的类型实现该接口并将责任委托给该对象.

所以你会有这样的事情:

   public interface PersistenceManager {
        public void fetchData( Object criteria );
        public void saveData( Object toSave );
        public void deleteData( Object toDelete );
        public void updateData( Object toUpdate );
   }  
Run Code Online (Sandbox Code Playgroud)

和不同的实现

  public class FilePersistence implements PersistanceManager {
        public void fetchData( Object criteria ) {
                  // open file
                  // read it
                  // find the criteria
                  // build the data
                  // close it.
         }
        public void saveData( Object toSave ) {
                 // open file, go to EOF etc. 
        }
        public void deleteData( Object toDelete ){
           ....
        }
        public void updateData( Object toUpdate ){
          ....
        }
  }
Run Code Online (Sandbox Code Playgroud)

其他类型将根据其逻辑实现.网络将处理套接字和流,DB将处理JDBC,ResultSets等XML与节点等.etc.

  public class NetworkPersistence implements PersistanceManager {
        public void fetchData( Object criteria ) {
             // Socket stuff
         }
        public void saveData( Object toSave ) {
             // Socket stuff
        }
        public void deleteData( Object toDelete ){
           // Socket stuff
        }
        public void updateData( Object toUpdate ){
           // Socket stuff
        }
  }


  public class DataBasePersistence implements PersistanceManager {
        public void fetchData( Object criteria ) {
             // JDBC stuff
         }
        public void saveData( Object toSave ) {
             // JDBC  stuff
        }
        public void deleteData( Object toDelete ){
           // JDBC  stuff
        }
        public void updateData( Object toUpdate ){
           // JDBC  stuff
        }
  }
Run Code Online (Sandbox Code Playgroud)

最后,您只需委托调用.

后来:

public YouProblematicClass { // not longer that problematic

    PersistamceManager persistance = // initialize with the right one.


        public void fetchData( Object criteria ) {
             // remove the switch and replace it with:
             this.persistance.fetchData( criteria );
         }
        public void saveData( Object toSave ) {
             // switch removed
             this.persistance.saveData(  toSave );
        }
        public void deleteData( Object toDelete ){
           this.persistance.deleteData( toDelete );
        }
        public void updateData( Object toUpdate ){
           this.persistance.updateData( toUpdate );
        }
  }
Run Code Online (Sandbox Code Playgroud)

因此,您只需根据类型只为一次创建持久性管理器的正确实例.然后通过多态来解决所有调用.这是面向对象技术的关键特性之一.

如果您决定需要另一个持久性管理器,则只需创建新实现并分配给该类.

 public WavePersistance implements PersistanceManager {

        public void fetchData( Object criteria ) {
             // ....
         }
        public void saveData( Object toSave ) {
             //  ....
        }
        public void deleteData( Object toDelete ){
           //  ....
        }
        public void updateData( Object toUpdate ){
           //  ....
        }
   }
Run Code Online (Sandbox Code Playgroud)

  • 非常好的答案! (2认同)

pto*_*mli 16

据推测,你正在努力解决案件不变的要求.通常这是代码味道,但有些事情你可以做.您可能想要提出并链接到另一个问题,详细说明您尝试切换的原因.

Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());

String key = "something";
if (map.contains(key)) {
    Object o = map.get(key);
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,您可能希望映射到"处理程序",例如

interface Handler {
    public void doSomething();
}
Run Code Online (Sandbox Code Playgroud)

然后使这一切变为查找.

if (map.contains(key)) { map.get(key).doSomething(); }
Run Code Online (Sandbox Code Playgroud)

再次,这有点气味,所以请发一个说明推理的问题.

  • 如果常量是一种痛苦,你也可以使用枚举. (3认同)

Tay*_*ese 5

重构代码以使用多态可以摆脱对switch语句的需求。但是,切换有一些合法用途,因此这取决于您的情况。

  • 是的-这是众所周知的重构-http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html (3认同)