由Collections.unmodifiableList引起的重構

今天閱讀源碼的時候,無心中看到了Collections.unmodifiableList的用法,由於之前沒有這樣作過,因此查詢了他的API,是這樣寫的php

public static <T> List<T> unmodifiableList(List<? extends T> list)html

參數:list--這是一個不可修改視圖是要返回的列表中。java

返回值:在方法調用返回指定列表的不可修改視圖。數據結構

一、用法探討:ide

 1 public class CollectionsListDemo {  2 public static void main(String[] args) {  3  4 List<String> list = new ArrayList<String>();  5 list.add("aa");  6 list.add("bb");  7  8 System.out.println("初始化前: "+ list);  9 10 //實現 unmodifiable 11 List<Character> immutablelist = Collections.unmodifiableList(list); 12 13 //修改 list 14 immutablelist.add("zz"); 15  }} 16 17 結果: 18 19 初始化前:: [aa, bb] 20 21 Exception in thread "main" java.lang.UnsupportedOperationException

二、繼續追蹤,到底什麼場景遇到呢?重構是怎麼寫的的?函數

在《重構——改善既有代碼的設計》一書中,有一種重構手法叫Encapsulate Collection  ,(封裝集合),ui

定義是:讓函數返回這個集合的副本,並在這個類中提供添加/移除集合的副本this

爲了演示該重構手法spa

這本書介紹的是:咱們常常用集合,Collection,多是Array,ArrayList,set,vector保存一組實例,這樣的類一般也會提供針對該集合的取值與設值函數設計

可是集合的處理方式和其餘種類略有不一樣,取值函數不該該返回集合自己,由於這會讓用戶得以修改集合的內容而集合擁有者去一無所知,這樣會對用戶 暴露過多的對象的內部結構信息。若是一個取值函數確實要返回多個值,他應該避免用戶直接操做對象內保存的集合,並隱藏對象內與用戶無關的的數據結構

此外,不該該爲這個集合提供一個設置函數,可是應該提供對象內集合自己添加/刪除的函數,這樣,集合擁有者(對象)就能夠控制集合元素的添加與刪除

若是作到了上邊的一點,集合就很好的封裝起來,這樣就下降了集合擁有者和用戶之間的耦合度

經常使用到的作法:

(1)加入爲集合添加/移除元素的函數

(2)將保存的集合的字段初始化一個空的集合

三、下面對上邊的內容的例子介紹:

原來我這樣寫的:

 1 import java.util.List;  2  3 public class Student  4 {  5 private String userName ;  6  7 private List<String> courses ;  8  9 10 public Student (String userName , List<String> courses) 11  { 12 this.userName = userName; 13 this.courses = courses; 14  } 15 16 public String getUserName() 17  { 18 return userName ; 19  } 20 21 public void setUserName(String userName) 22  { 23 this.userName = userName; 24  } 25 26 public List<String> getCourses() 27  { 28 return courses ; 29  } 30 31 public void setCourses(List<String> courses) 32  { 33 this.courses = courses; 34  } 35 36 37 38 }

重構後,按照上面介紹的原則,這樣重構:

 1 import java.util.ArrayList;  2 import java.util.Collections;  3 import java.util.List;  4  5 public class Student  6 {  7 private String userName ;  8  9 private List<String> courses ; 10 11 public Student (String userName , List<String> courses) 12  { 13 this.userName = userName; 14 this.courses = courses; 15  } 16 17 public String getUserName() 18  { 19 return userName ; 20  } 21 22 public void setUserName(String userName) 23  { 24 this.userName = userName; 25  } 26 27 public void addCourse(String course) 28  { 29  courses.add(course); 30  } 31 32 public boolean removeCourse(String course) 33  { 34 return courses .remove(courses ); 35 36  } 37 38 public List<String> getCourses() 39  { 40 return Collections.unmodifiableList( courses); 41  } 42 43 public static void main(String[] args) 44  { 45 List<String> list = new ArrayList<String>(); 46 list.add( "數學"); 47 list.add( "語文"); 48 Student s = new Student("lily" , list); 49 50 List<String> anotherList = s.getCourses(); 51 52 /** 53 * throws java.lang.UnsupportedOperationException should replace with 54 * s.addCourse(String course) 55 */ 56 anotherList.add( "英語"); 57 58 // 不會走到這一步,由於上邊拋出了異常 59 System. out.println("lily's course.length = " + s.getCourses().size()); 60 } 61 62 }

四、總結

使用這種方法重構的意義:就比如咱們網上購物同樣,你能夠往購物車添加本身想買的東西,可是商戶不能在不通知顧客(咱們)的狀況下,就職意的添加商品,並修改商品的價格等,入口只能是一個,也就是在顧客手中。比喻可能不是很恰當,反正意思大概就是這樣。

相關文章
相關標籤/搜索