本文通过示例来谈谈慎用缺省构造函数的一种设计场景。——以JAVA为例展开讨论。
为了便于讨论,我们假定需要建模一个Student,包括姓名和出生地两个属性。我们看到不少下面的代码:
public class Student {
private String name = null;
private String birthPlace = null;
public Student() {
}
public void setName(String name) {
this.name = name;
}
public void setBirthPlace(String birthPlace) {
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public String getBirthPlace() {
return birthPlace;
}
}
import org.junit.Test;
public class StudentTest {
@Test
public void test() {
final String NAME = "John";
final String BIRTH_PLACE = "Hawaii";
Student student = new Student();
student.setName(NAME);
student.setBirthPlace(BIRTH_PLACE);
assert(NAME.equals(student.getName()));
assert(BIRTH_PLACE.equals(student.getBirthPlace()));
}
}
对于以上的设计方法,其适合的语义是:
符合这种语义的对象非常多,比如表示(二维)平面上的一个点Point2d就适合用上面的设计方法。
本文讨论的是另外一种情况,即有如下语义要求:
对于我们前面给出的Student例子,我们假定Name不能修改,如果有新的名字,就需要新增一个属性(如aliasName)来表示;而出生地也是固定的。对于这种情况,虽然前面给出的代码也能够较好地工作,但从设计语义上来讲,是不太合适的。
对于这种情况,通常推荐如下的做法:
因此,前面的class Student需要重构成下面的代码:
public class NewStudent {
private String name = null;
private String birthPlace = null;
public NewStudent(String name, String birthPlace) {
this.name = name;
this.birthPlace = birthPlace;
}
public String getName() {
return name;
}
public String getBirthPlace() {
return birthPlace;
}
} @Test
public void testNewStudent() {
final String NAME = "John";
final String BIRTH_PLACE = "Hawaii";
NewStudent student = new NewStudent(NAME, BIRTH_PLACE);
assert(NAME.equals(student.getName()));
assert(BIRTH_PLACE.equals(student.getBirthPlace()));
}
——要知道,通常一个项目都有大量的代码,数千上万是非常常见的事情。当遍地充斥着各种各样低质量语义的代码时,整个项目就会产生大量的无效代码,这对于项目维护是一件很可怕的事情。
我们写的每一行代码,都是在向读者(包括你自己)表达一种设计思想。可以工作的代码未必是质量优秀的代码,显然我们要追求的是后者。
原文:http://blog.csdn.net/a_flying_bird/article/details/38424387