java的Collections是非常常见的类了,但是非常惭愧,但Collections.unmodifiableList真心没用过。于是乎看了看网上的说法,这篇文章说的不错:
在《重构——改善既有代码的设计》一书中,有一种重构手法叫Encapsulate Collection(封装集群),为了演示该重构手法,我写了四个类,通过对比重构前后的代码,加深对这一重构手法的理解。
类Student有一ArrayList属性,如果没有阅读《重构——改善既有代码的设计》一书,很多人可能会像我一样(我就是这样),如下设计类Student。但是,如果通过Student.getCourses()获得对ArrayList属性引用后,就可以任意为Student对象添加“课程”,而Student对象对此一无所知,这不符合面向对象编程的习惯。
重构前的代码
Students.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package com.readonlylist; import java.util.ArrayList; public class Student { private String name; private ArrayList courses; public Student(String name, ArrayList courses) { this.name = name; this.courses = courses; } public ArrayList getCourses() { return courses; } public void setCourses(ArrayList courses) { this.courses = courses; } public String getName() { return name; } public void setName(String name) { this.name = name; } |
Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.readonlylist; import java.util.ArrayList; public class Test { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("001"); list.add("002"); Student s = new Student("Tom", list); ArrayList anotherList = s.getCourses(); anotherList.add("999"); System.out.println("Tom's course.length = " + s.getCourses().size()); } |
重构后的代码如下:
Student1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package com.readonlylist; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Student1 { private String name; private ArrayList courses; public Student1(String name, ArrayList courses) { this.name = name; this.courses = courses; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void addCourse(String course) { courses.add(course); } public String removeCourse(String course) { boolean removed = courses.remove(courses); if (removed) { return course; } else { return null; } } public List getCourses() { return Collections.unmodifiableList(courses); } |
Test1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.readonlylist; import java.util.List; import java.util.ArrayList; public class Test1 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("001"); list.add("002"); Student1 s = new Student1("Tom", list); List anotherList = s.getCourses(); /** * throws java.lang.UnsupportedOperationException * should replace with s.addCourse(String course) */ anotherList.add("999"); // never reached System.out.println("Tom's course.length = " + s.getCourses().size()); } |
重构后,Student1类,仅对外提供的getCourses()方法,而没有setCourses()方法,而且通过getCourses()方法获得的courses是“只读的”,如果你试图向其添加一个新课程,则抛出java.lang.UnsupportedOperationException。你必须通过Student1.addCourse()来向特定的Student1对象添加一个新课程。就好像,你必须让顾客自己向购物车里放食物,而不能在顾客毫不知情下,偷偷向其购物车里放食物。
真是万物皆通情理啊!
原文地址已不可查,依然感谢原作者!
0 条评论