重构具有多个职责的Java类

时间:2014-01-23 05:32:50

标签: java refactoring

public class MyObject
{
    public static enum Type {A, B, C, D;}

    public static final int ID_MAIN = 1;
    public static final int ID_MAIN_UK = 2;
    public static final int ID_MAIN_US = 3;
    public static final int ID_SUB = 4;
    // lots more constants here

    public static final String DESCRIPTION_1 = "Desc Full Name";
    public static final String DESCRIPTION_2 = "Desc2 Full Name";
    // lots more constants here

    private int id;

    public MyObject(final int id)
    {
        this.id = id;
    }

    //simple getter 
    public int getID() { return this.id;}

    // real responsibility of the class is in the following two methods
    public static String getDescription()
    {
         switch(id)
         {
              case MyObject.ID_MAIN:
              case MyObject.ID_MAIN_UK:
                  return MyObject.DESCRIPTION_1;
              case MyObject.ID_SUB:
                  return MyObject_Description_2;
              default:
                   // throw IllegalArgException
          }        
     }

     public static Type getType(int id)
     {
         switch(id)
         {
             case MyObject.ID_MAIN:
             case MyObject.ID_SUB:
                 return Type.A;
             case MyObject.ID_MAIN_UK:
             case MyObject.ID_MAIN_US:
                 return Type.B;
             default:
                 return Type.Undefined;
         }
      }
 }

基本上,有一个ID映射到描述和类型。在构造类时传入此ID,它应映射到已包含在类中的一组常量。如果id不是常量列表的一部分,则在尝试获取映射到id的描述时会引发错误,如果查询类型,则返回“Unknown”类型。 ID将描述映射到一组常量。相同的ID映射到某个类型(定义为枚举)。

这段代码非常丑陋,因为顶部定义了大量的常量,这使得switch语句非常臃肿。有没有一种简单的方法可以在不改变公共接口的情况下重构它?这似乎很简单,但无论你如何分割,它似乎都很难看。如何简化这些映射以使代码更简洁?

我正在考虑在文本文件中表示映射,并且在哈希映射中有一个包含简单容器的管理器类。构造管理器类时,它将通过读取文本文件并将它们映射到ID来创建对象。当使用ID查询管理器时,它只会调用相应的get方法,例如:

class Manager 
{
     private HashMap<int, MyObject> objectMap;

     public Manager() {} //construct the object map
     public String getDescription(int id) { return objectMap.get(id).getDescription();}
     public Type getType(int id) { return objectMap.get(id).getType();}
}

class DataContainer
{
     private String description;
     private Type type;


     public DataContainer(String desc, Type type) {//set mem vars}
     public String getDescription() //simple getter
     public Type getType() //simple getter
 }

但这个解决方案似乎太复杂了。有没有更好的解决方案,最好能将所有内容保持在一个类中?

2 个答案:

答案 0 :(得分:0)

在Java中,枚举可以有方法。例如,下面一个接受ID和描述并提供一些访问者。

public enum Type {
        MAIN(1, "desc1"),
        UK(2, "desc2"),
        SUB(4, "desc4");

        private int id;
        private String desc;

        Type(int id, String desc) {
            this.id = id;
            this.desc = desc;
        }
        public String getDescription() {
             return  desc;
        }

        public int getType() {
            //return id;
            return 1+2 + 3+ id;
        }
    }

您可以使用它来改进设计。

答案 1 :(得分:0)

您可以执行以下操作。这将更加清洁和易于管理。

public enum Type
{

    MAIN(1, "Main Description"),
    MAIN_UK(2, "Main UK Description"),
    //....
    //Define all the types
    //....
    UNKNOWN(-1, "Unknown Type");

    private int id;
    private String description;

    private Type(int id, String description)
    {
        this.id = id;
        this.description = description;
    }

    public static Type getById(int id)
    {
        for (Type type : Type.values())
        {
            if (id == type.getId())
            {
                return type;
            }
        }

        return Type.UNKNOWN;
    }

    public final int getId()
    {
        return id;
    }

    public final String getDescription()
    {
        return description;
    }
}

public class MyObject
{
    private int id;
    private Type type;

    public MyObject(int id)
    {
        this.id = id;
        this.type = Type.getById(id);
    }

    public int getId()
    {
        return id;
    }

    public Type getType()
    {
        return type;
    }

    public String getDescription()
    {
        return type.getDescription();
    }
}