本文通过示例来谈谈慎用缺省构造函数的一种设计场景。——以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