Collections.unmodifiableList方法的使用與場景

在《重構——改善既有代碼的設計》一書中,有一種重構手法叫Encapsulate Collection
(封裝集羣),爲了演示該重構手法,我寫了四個類,經過對比重構先後的代碼,加深對
這一重構手法的理解。java

類Student有一ArrayList屬性,若是沒有閱讀《重構——改善既有代碼的設計》一書,
不少人可能會像我同樣,以下設計類Student。可是,若是經過Student.getCourses()
得到對ArrayList屬性引用後,就能夠任意爲Student對象添加「課程」,而Student對象
對此一無所知,這不符合面向對象編程的習慣。web

package com.readonlylist;編程

import java.util.ArrayList;this

public class Student
{
    private String name;設計

    private ArrayList<String> courses;orm

    public Student(String name, ArrayList<String> courses)
    {
 this.name = name;
 this.courses = courses;
    }
    
    public ArrayList<String> getCourses()
    {
        return courses;
    }對象

    public void setCourses(ArrayList<String> courses)
    {
        this.courses = courses;
    }rem

    public String getName()
    {
        return name;
    }get

    public void setName(String name)
    {
        this.name = name;
    }    
}it

package com.readonlylist;

import java.util.ArrayList;

public class Test
{
    public static void main(String[] args)
    {
 ArrayList<String> list = new ArrayList<String>();
 list.add("001");
 list.add("002");
        Student s = new Student("Tom", list);
        
        ArrayList<String> anotherList = s.getCourses();
        
        anotherList.add("999");
        
        System.out.println("Tom's course.length = " + s.getCourses().size());
    }
}

重構後的Student類以下所示:

package com.readonlylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Student1
{
    private String name;

    private ArrayList<String> courses;
    
    public Student1(String name, ArrayList<String> 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<String> getCourses()
    {
 return Collections.unmodifiableList(courses);
    }
}

package com.readonlylist;

import java.util.List;
import java.util.ArrayList;

public class Test1
{
    public static void main(String[] args)
    {
 ArrayList<String> list = new ArrayList<String>();
 list.add("001");
 list.add("002");
        Student1 s = new Student1("Tom", list);
        
        List<String> 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對象添加一個新課程。就好像,你必須讓顧客本身向購物車裏放食物,而不能在顧客絕不知情下,偷偷向其購物車裏放食物。

相關文章
相關標籤/搜索