浏览 1589 次
锁定老帖子 主题:代码重构之字符串与包的讨论
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-08
在CourseSession中增加两个变量页眉和页脚 private static String ROSTER_REPORT_HEADER = "页眉,学生信息报表"; private static String ROSTER_REPORT_FOOTER = "页脚,学生信息报表"; 然后增加方法getRosterReport返回报表信息。 String getRosterReport(){ StringBuilder buffer = new StringBuilder(); buffer.append(ROSTER_REPORT_HEADER); Student student = students.get(0); buffer.append(student.getName()); buffer.append('\n'); student = students.get(1); buffer.append(student.getName()); buffer.append('\n'); buffer.append(ROSTER_REPORT_FOOTER+students.size()+'\n'); return buffer.toString(); }在很多地方使用了'\n'表示缓换行,这样做不仅有冗余,而且难以移植----不同平台使用不同的特殊字符序列表示换行。类java.lang.System中包含一个方法getProperty,此方法以一个系统属性的键值作为参数,并返回与该键值相关的系统属性。其中一个属性是line.separator。参考java API文档,在unix中该属性的值为'\n',然而在windows中,值为'\r\n'。应该使用getProperty(line.separator)弥合不同平台直接的差异。 在CourseSession类中定义一个换行常量 static final String NEWLINE = System.getProperty("line.separator"); 然后代码相应变为 private static String ROSTER_REPORT_HEADER = "Student"+NEWLINE+"-----"+NEWLINE; private static String ROSTER_REPORT_FOOTER = NEWLINE + "#Student"; String getRosterReport(){ StringBuilder buffer = new StringBuilder(); buffer.append(ROSTER_REPORT_HEADER); Student student = students.get(0); buffer.append(student.getName()); buffer.append(NEWLINE ); student = students.get(1); buffer.append(student.getName()); buffer.append(NEWLINE); buffer.append(ROSTER_REPORT_FOOTER+students.size()+'\n'); return buffer.toString(); }单职责原则: 学生信息系统不断需要新的报表,可以预见,因为增加报表,需要不断地改变类CourseSession。面向对象有一个基本的设计原则:一个类只做好一件事,由于只做一件事,所以应该只有一个动机。这就是单职责原则 生成报表,如报名表,是改变类CourseSession 的另一个动机,违背了单职责原则。 创建一个新类RosterReporter 来生成报表。 public class RosterReporter { static final String NEWLINE = System.getProperty("line.separator"); //换行常量 private static String ROSTER_REPORT_HEADER = "Student"+NEWLINE+"------"+NEWLINE; private static String ROSTER_REPORT_FOOTER = NEWLINE + "#Student"; private CourseSession session; public RosterReporter(CourseSession session) { super(); this.session = session; } String getRosterReport(){ StringBuilder buffer = new StringBuilder(); buffer.append(ROSTER_REPORT_HEADER); for(Student student:session.getAllStudents()){ buffer.append(student.getName()); buffer.append(NEWLINE); } buffer.append(ROSTER_REPORT_FOOTER+session.getAllStudents().size()+NEWLINE); return buffer.toString(); } Date createDate(int year,int month,int date){ GregorianCalendar calendar = new GregorianCalendar(); calendar.clear(); calendar.set(Calendar.YEAR, year-1900); calendar.set(Calendar.MONTH, month-1); calendar.set(Calendar.DAY_OF_MONTH, date); return calendar.getTime(); } }在CourseSession类和RosterReporter中都需要createDate工具方法。这个很明显是一个小重复,如果您不进行重构,您就打开了大规模的重复的大门,很快您的系统中就会出现代价高昂的重复。在一个大型系统中,或许会有很多创建日期的方法,每个方法都有类似的代码。 可以创建一个日期工具类 DateUtil来统一日期的创建和维护。 public class DateUtil { /** * * @param year 年 * @param month 月份 * @param date 月中的天数 * @return 返回一个根据参数year,month,date组成的日期实例 */ //可以写成静态方法。 public static Date createDate(int year,int month,int date){ GregorianCalendar calendar = new GregorianCalendar(); calendar.clear(); calendar.set(Calendar.YEAR, year-1900); calendar.set(Calendar.MONTH, month-1); calendar.set(Calendar.DAY_OF_MONTH, date); return calendar.getTime(); } } 包结构的一些约定 迄今为止,您编写的类都在包studentinfo包中,典型的组织包的方法是:分离用户接口类和表示业务逻辑的底层类。用户接口负责与最终用户的交互。 如下面的包结构是根据j2ee的mvc模式来划分的,cn.com.common包中放工具类:如日期生产类等,接口(cn.com.dao/cn.com.service)和实现类(cn.com.daoimpl/cn.com.serviceimpl)放在不同的包中,且包的分类都是根据模块来分类的。 类的访问权限 为了更安全的编程,推荐的顺序是:首先是最受限的访问,然后需要时打开相应的访问权限。暴露太多的类给客户,会导致客户对系统的细节产生不必要的依赖。如果您改变了某些细节,客户的代码就可能无法继续工作,而且,打开太多的访问权限,会使您的代码逐渐被破坏。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |