看来Java构造器模式,决定动手体验下。构造器模式是什么?干什么用的?推荐大家看下ITEYE的一篇文章
http://www.iteye.com/topic/71175 了解构造器模式对于系统的重构,也是很有帮助的。例如,可以优化多构造器类的设计。
首先,我先寻找一个应用场景。拿民工和设计师来写固然可以,但觉得有点类似写Hello word的感觉。学习编程语言和设计模式,很多时候只有将学到的东西和实际应用结合起来的时候,才会深入体会,获取精髓。
Effective Java里说,当遇到多个构造器参数时,考虑用构造器模式。里面有个商品的例子。这让我想到了熟悉的学生信息管理系统。
拿研究生来说吧,入学考试后先进行面试和体检,然后是录取,最后是入学分班。这几个阶段对学生的信息需求是不一样的。
我们首先基于以下假设:
1、体检时只需要知道我们的姓名、性别、年龄和身高等信息。
2、录取的时候,需要在体检基本信息的基础上添加院系、年级等信息。
3、入学分班后,需要添加班号(班级编号)等信息。
4、正式开学后,为了便于管理,又需要完善身份证、学号、实验室名称和宿舍地址等信息。
好吧,现在我们动手写这个学生信息管理系统。先要创建一个名为Student的类,为了满足4个阶段创建用户信息的需要
,我们可能需要4个构造函数。
- package com.icecode.data;
-
- public class Student {
- private String name;
- private int age;
- private int height;
- private int sex;
-
-
- private String schoolName;
- private String profession;
-
- private int gradeNo;
-
-
- private String idCard;
- private String stuNo;
- private String labName;
- private String dormitoryAddress;
-
- public Student(String name, int age, int height, int sex) {
- super();
- this.name = name;
- this.age = age;
- this.height = height;
- this.sex = sex;
- }
-
-
- public Student(String name, int age, int height, int sex,
- String schoolName, String profession) {
- super();
- this.name = name;
- this.age = age;
- this.height = height;
- this.sex = sex;
- this.schoolName = schoolName;
- this.profession = profession;
- }
-
- public Student(String name, int age, int height, int sex,
- String schoolName, String profession, int gradeNo) throws Exception {
- super();
- this.name = name;
- this.age = age;
- this.height = height;
- this.sex = sex;
- this.schoolName = schoolName;
- this.profession = profession;
- this.gradeNo = gradeNo;
- if(isValidStudent() == false)
- throw new Exception("不合法的学生信息,同名的学生不能分到同一个班级...");
- }
-
-
- public boolean isValidStudent(){
- boolean flag = true;
-
- return flag;
- }
-
- public Student(String name, int age, int height, int sex,
- String schoolName, String profession, int gradeNo, String idCard,
- String stuNo, String labName, String dormitoryAddress) {
- super();
- this.name = name;
- this.age = age;
- this.height = height;
- this.sex = sex;
- this.schoolName = schoolName;
- this.profession = profession;
- this.gradeNo = gradeNo;
- this.idCard = idCard;
- this.stuNo = stuNo;
- this.labName = labName;
- this.dormitoryAddress = dormitoryAddress;
- }
-
- }
当然,以上这个Student类,可以就创建一个构造器,当然这个构造器必须是参数最多的那个。但是这样,编写体检中心信息管
理的程序员不愿意了,它不愿意使用一个需要这么多参数的构造器,因为对他有用的参数就4个。其它模块的程序可能也不大高兴,
因为他们也不愿意使用这样的构造器。同时,如果学校的某个部门突然提出需要其它一些学生信息,比如说学生的4、6级成绩,这
个看似通用的构造器就不适用了,而且修改该构造器代价很大。其它模块的程序员都得配合。
也许有人会问,为什么不使用JavaBean使用的Set方法呢?这种方法有一个缺陷,因为构造过程被分配到了几个调用中,在构
造过程中JavaBean可能处于不一致状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。(引用:《Effective Java》)
是啊,我们总不能控制类的使用者按照一定顺利来调用不同参数的Set方法,再在最后一个set方法中做校验吧?
所以比较满意的方法是根据大家的需要创建不同的构造器。
这样,当参数不断增多的时候,大家都根据自己的需要创建一个自己的构造器。慢慢的,构造器越来越多,代码变得越来越难
理解。即使有一天,系统的设计者想重新设计这个构造器,也变得异常困难。
当系统的设计者正在为这种需求苦恼的时候,我们发现了Builder模式,好吧,我们现在就想想怎么用Builder模式来解决我们
的需求难题。
试想,哪些信息是必须有的,我们只需要一个基础构造器。其它的信息通过类似JavaBean所使用的Set方法set进去,一样可以
达到我们的目的。具体怎么做?我们先贴出代码吧。
测试代码
- public class Test {
- public static void main(String[] args){
- Student stu = new Student.Builder("icecode", 22, 178, 1)
- .setSchoolName("BUPT").setProfession("Computer Science and
-
- Technology").
- setGradeNo(20091012)
- .build();
- System.out.println(stu.toString());
- }
- }
由上看见,使用Builder模式减少了构造器,提供了通用的入口,便于进行合法性校验。前面系统设计中的问题,也迎刃而解了。
当然了,构造器的用途很多,自己只是拿它在多构造器类的重构中的使用来体验。