看来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; //0表示男性,1表示女性,其它值非法
private String schoolName;
private String profession;
//要求分班的时候,名字相同的同学不能分配到一个班级
private int gradeNo;//年级编号
//扩展信息
private String idCard;//身份证号
private String stuNo;//学号
private String labName;//实验室名称
private String dormitoryAddress;//宿舍地址
/**
* 创建一个基本学生信息 ,例如在研究生入学体检时,不需要专业、年级信息,
* 因此,可以只适用必须的参数创建一个基本信息
* @param name
* @param age
* @param height
* @param sex
*/
public Student(String name, int age, int height, int sex) {
super();
this.name = name;
this.age = age;
this.height = height;
this.sex = sex;
}
/**
* 创建一个基本学生信息 ,研究生正式录取后,学校的学生信息管理系统需要学生基本信息
* @param name
* @param age
* @param height
* @param sex
* @param schoolName
* @param profession
*/
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;
}
/**
* 开学了,为了教学方便,学校进行了分班,同时要求在创建分班的时候,
* 要求名字相同不分到同一个班级
* @param name
* @param age
* @param height
* @param sex
* @param schoolName
* @param profession
* @param gradeNo
* @throws Exception
*/
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("不合法的学生信息,同名的学生不能分到同一个班级...");
}
/**
* 学生信息合法性校验
* @return
*/
public boolean isValidStudent(){
boolean flag = true;
//TODO 进行用户信息合法性校验
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进去,一样可以
达到我们的目的。具体怎么做?我们先贴出代码吧。
package com.icecode.data;
public class Student {
private final String name;
private final int age;
private final int height;
private final int sex; //0表示男性,1表示女性,其它值非法
private final String schoolName;
private final String profession;
//要求分班的时候,名字相同的同学不能分配到一个班级
private final int gradeNo;//年级编号
//扩展信息
private final String idCard;//身份证号
private final String stuNo;//学号
private final String labName;//实验室名称
private final String dormitoryAddress;//宿舍地址
private Student(Builder builder) {
this.name = builder.name;
this.age = builder.age;
this.height = builder.height;
this.sex = builder.sex;
this.schoolName = builder.schoolName;
this.profession = builder.profession;
this.gradeNo = builder.gradeNo;
this.idCard = builder.idCard;
this.stuNo = builder.stuNo;
this.labName = builder.labName;
this.dormitoryAddress = builder.dormitoryAddress;
}
public static class Builder{
private String name;
private int age;
private int height;
private int sex; //0表示男性,1表示女性,其它值非法
private String schoolName;
private String profession;
//要求分班的时候,名字相同的同学不能分配到一个班级
private int gradeNo;//年级编号
//扩展信息
private String idCard;//身份证号
private String stuNo;//学号
private String labName;//实验室名称
private String dormitoryAddress;//宿舍地址
public Builder(String name, int age, int height, int sex) {
super();
this.name = name;
this.age = age;
this.height = height;
this.sex = sex;
}
public Builder setSchoolName(String schoolName) {
this.schoolName = schoolName;
return this;
}
public Builder setProfession(String profession) {
this.profession = profession;
return this;
}
public Builder setGradeNo(int gradeNo) {
this.gradeNo = gradeNo;
return this;
}
public Builder setIdCard(String idCard) {
this.idCard = idCard;
return this;
}
public Builder setStuNo(String stuNo) {
this.stuNo = stuNo;
return this;
}
public Builder setLabName(String labName) {
this.labName = labName;
return this;
}
public Builder setDormitoryAddress(String dormitoryAddress) {
this.dormitoryAddress = dormitoryAddress;
return this;
}
//构造器入口
public Student build(){
return new Student(this);
}
}
@Override
public String toString() {
return "Students [name=" + name + ", age=" + age + ", height=" + height
+ ", sex=" + sex + ", schoolName=" + schoolName
+ ", profession=" + profession + ", gradeNo=" + gradeNo + "]";
}
}
测试代码
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模式减少了构造器,提供了通用的入口,便于进行合法性校验。前面系统设计中的问题,也迎刃而解了。
当然了,构造器的用途很多,自己只是拿它在多构造器类的重构中的使用来体验。
分享到:
相关推荐
JAVA相关基础知识 1、面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用...
设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Strategy(策略) 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Chain of ...
超级有影响力的Java面试题大全文档 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。...
:grinning_face:点击查看电子书,体验更好 :backhand_index_pointing_right: 创建型 (Creational)Java Kotlin结构型(Structural)适配器模式(Adapter Class/Object Pattern) Java桥接模式(Bridge Pattern) ...
,lyadmin全称零云lyadmin是一套轻量级通用后台,采用JFinal+Vue+Element制作,内置系统设置、上传管理、权限管理、模块管理、插件管理等功能,独有的Builder页面自动生成技术节省50%开发成本 微信小程序是腾讯公司...
2分法-通用存储过程分页(top max模式)版本(性能相对之前的not in版本极大提高) 分页存储过程:排序反转分页法 优化后的通用分页存储过程 sql语句 一些Select检索高级用法 SQL server 2005中新增的排序函数及应用 ...
目录页 下一页 ... 虽然 PHP5 还没有正式发布(开发版本已经提供下载),但我们现在就可以开始体验一下新的版本将要带给我们的惊喜。...这三大特点为: * 新的对象模式 (New ...Power by Softscape HTML Builder 3
// 注册autofac打标签模式builder.RegisterModule(new AutofacAnnotationModule(typeof(AnotationTest).Assembly));//如果需要开启支持循环注入//builder.RegisterModule(new AutofacAnnotationModule(typeof(Ano
Visual SiteBuilder网站综合管理平台(简称VSB)是基于JAVA技术开发的网站管理软件。该系统融合先进的网站建设周期管理思想,集成网站可视化设计,内容管理,虚拟主机,用户管理,审核管理等经典应用,全面覆盖了...
综上所述,“认我测”在线认证检测系统,率先填补了认证检测领域移动端的空缺,提供了Web浏览器+移动端的双端访问模式,给用户提供了多种访问途径,真正实现了用户和检测机构的随时随地在线下单检测。 关键词:...
5、报表数据来源丰富:支持绑定(报表数据拉模式)与非绑定(报表数据推模式),一切数据库数据与其它数据都可以作为报表数据源。 6、提供图表功能,包括:饼图、叠加饼图、柱状图、气泡图、折线图、曲线图、散列点图等...
5、报表数据来源丰富:支持绑定(报表数据拉模式)与非绑定(报表数据推模式),一切数据库数据与其它数据都可以作为报表数据源。 6、提供图表功能,包括:饼图、叠加饼图、柱状图、气泡图、折线图、曲线图、散列点图等...
5、报表数据来源丰富:支持绑定(报表数据拉模式)与非绑定(报表数据推模式),一切数据库数据与其它数据都可以作为报表数据源。 6、提供图表功能,包括:饼图、叠加饼图、柱状图、气泡图、折线图、曲线图、散列点图等...
5、报表数据来源丰富:支持绑定(报表数据拉模式)与非绑定(报表数据推模式),一切数据库数据与其它数据都可以作为报表数据源。 6、提供图表功能,包括:饼图、叠加饼图、柱状图、气泡图、折线图、曲线图、散列点图等...
5、报表数据来源丰富:支持绑定(报表数据拉模式)与非绑定(报表数据推模式),一切数据库数据与其它数据都可以作为报表数据源。 6、提供图表功能,包括:饼图、叠加饼图、柱状图、气泡图、折线图、曲线图、散列点图等...
Builder 模式来创建,使用方式就和 Android 里面的AlertDialog一样,通过 Builder 去构建一个 PageLayout。最后的样子是长这样的:方法注释showLoading()显示 loadingshowError()显示错误布局showEmpty()显示空布局...
25.4.4 Gestures Builder应用程序 25.5 参考资料 25.6 小结 第26章 传感器 26.1 什么是传感器 26.1.1 检测传感器 26.1.2 可以了解的传感器信息 26.2 获取传感器事件 26.3 解释传感器数据 ...
25.4.4 Gestures Builder应用程序 25.5 参考资料 25.6 小结 第26章 传感器 26.1 什么是传感器 26.1.1 检测传感器 26.1.2 可以了解的传感器信息 26.2 获取传感器事件 26.3 解释传感器数据 ...
Support auto resize images. 具有特殊的对话框 <br/>With Style builder dialog box you can apply CSS style attributes directly to any HTML elements on your Web page.<br/> <br/> 支持内容...