Java软件设计

use*_*469 11 java

场景:

考虑下面的抽象类MeasurementType及其亚型AccelerationDensity:

public abstract class MeasurementType {
  protected String name;
  protected String[] units;

  public MeasurementType() {}

  public MeasurementType(String name) {
    this.name = name;
  }

  protected void setName(String name) {
    this.name = name;
  }

  protected String getName() {
    return name;
  }

  protected void setUnits(String[] values) {
    this.units = values;
  }
}

public class Acceleration extends MeasurementType {
  private String name;

  public Acceleration () {
    super();
  }

  public Acceleration(String name) {
    super();
  }

}

public class Density extends MeasurementType {
  private String name;

  public Density() {
    super();
  }

  public Density(String name) {
    super();
  }

}
Run Code Online (Sandbox Code Playgroud)

题:

对子类型的需求是什么,因为这些类中没有任何东西可以将它们区分开来(至少在我的实现中)赋予它们作为自己的实体存在的权利,但是为了示例,让我们说他们有自己的阵列包含每个不同类型的单位,所以密度将有千克,克等.加速将有英里,公里等.

最后我有这个运行类,我很快就编写了:

public class run {

  public run() {}

  public static MeasurementType testType() {
    Acceleration a = new Acceleration("meters per second");
    return (MeasurementType) a;
  }

  public static void main(String[] args) {
    MeasurementType mt = testType();
    System.out.println(mt.getClass().toString());
    System.out.println(mt.getClass().getName());

    String type = "acceleration";
    String[] units = new String[8];

    Object mType;
    if(type.equals("acceleration")) {
      mType = new Acceleration();
    } else if(type.equals("density")) {
      mType = new Density();
    } else {
      mType = new Object();
    }

    System.out.println(mType.getName());
  }
}
Run Code Online (Sandbox Code Playgroud)

这就是我遇到的问题.我正在使用字符串来确定我将实例化的类型,但问题是,默认情况下,在条件语句的末尾我实例化了Object,否则编译器会抱怨该mType变量不会被初始化.我不能创建一个MeasurementType对象,因为它是一个抽象类.

我想这更像是一个设计问题,但有没有更好的方法来确定要实例化的类?请假设它String type = "acceleration"来自下拉或某个用户​​界面的某个地方,我刚刚对其进行了硬编码,因为它对问题来说并不是必需的.

如果我看到它,有人可以解释这个设计错误.

Ric*_*gle 11

看看你的问题的关键,当字符串既不是"加速"也不是"密度"时该怎么办.

if(type.equals("acceleration")) {
  mType = new Acceleration();
} else if(type.equals("density")) {
  mType = new Density();
} else {
  mType = new Object();
}
Run Code Online (Sandbox Code Playgroud)

这是否表明程序中的某些内容已经破坏,这是不可挽回的错误?在这种情况下; 抛出一个例外.

if(type.equals("acceleration")) {
  mType = new Acceleration();
} else if(type.equals("density")) {
  mType = new Density();
} else {
  throw new RuntimeException("variable type is not a valid type, valid types are 'acceleration' and 'density'";
}
Run Code Online (Sandbox Code Playgroud)

这是你将要实现的目标; 例外是你的朋友.他们的意思是当程序错误时它尖叫到哪里和为什么然后你修复它.另一方面,静静地忽略这个问题会导致细微的错误和奇怪的行为,可能需要数天才能诊断出来.

另一方面,这是用户输入不当输入的标志吗?在这种情况下,验证输入,如果无效,则告诉最终用户并再次询问.

使用String像这样的s和if语句很可能根本就不是你想做的事情,但是假设它是你想要做的,那么这就是前进的方法(一个switch语句会稍好一些).


JB *_*zet 5

如果字符串不是重新计算的度量类型名称之一,则不应创建对象.您应该通过抛出异常来表示问题:

public MeasurementType fromString(String type) {
    if (type.equals("acceleration")) {
        return new Acceleration();
    } 
    else if (type.equals("density")) {
        return new Density();
    } 
    else {
        throw new IllegalArgumentException(type + " is not a known measurement type");
    }
}
Run Code Online (Sandbox Code Playgroud)


Ken*_*ent 5

像工厂一样的代码可能有所帮助.if equals and new Xxxx()如果您有100个子类型,则可以节省100个语句.

public abstract class MeasurementType {
    protected  String name;

    private static final Map<String, Class<? extends MeasurementType>> typeMap = new HashMap<>();
    static{
        typeMap.put("accelaration", Acceleration.class);
        typeMap.put("density", Density.class);
       //put here if you have others
    }

    public static MeasurementType getMeasurement(String keyStr) throws RuntimeException {
        if (typeMap.containsKey(keyStr)) {
            try {
                return typeMap.get(keyStr).newInstance();
            }
            catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("creation failed.");
            }
        }
            //this could be a speical exception type
        throw new RuntimeException("creation failed: unknown type"); 
    }

}
Run Code Online (Sandbox Code Playgroud)

在你的run类/方法中:

        String s = "accelaration";
        String s2 = "trash";
        MeasurementType t = null;

        try {
            t =MeasurementType.getMeasurement(s);
            t = MeasurementType.getMeasurement(s2); //throw ex
        }catch (RuntimeException e){
            //do something
        }
Run Code Online (Sandbox Code Playgroud)

  • 有点挑剔,但``RuntimeException`和`catch(Exception)`子句一样糟糕.抛出"IllegalArgumentException"的抛出,这是"ClassNotFoundException"的捕获.世界上有足够的口袋妖怪训练师转向开发者. (5认同)
  • 一般认为反射有点可怕吗? (3认同)