【設計模式與Android】原型模式——複製中心走出來的克隆人

什麼是原型模式程序員

 

所謂原型模式,就是用原型實例來指定建立對象的種類,並經過複製這些原型建立新的對象的設計模式。原型模式通常用於建立複雜的或者構建耗時的實例,或者用於只讀對象的修改。設計模式

 

原型模式的實現方式app

 

(1)淺拷貝ide

當代的每一個程序員小時候都玩過《尤里的復仇》這款遊戲,遊戲中的「尤里」陣營有個兵種叫「尤里複製人」,每一個尤里複製人都和尤里長得如出一轍,除了沒有坐騎以外。函數

public class Yuri{

    
private String name = "Yuri";

    
private ArrayList<String> words = new ArrayList<>();

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

    
public void addWord(String word){
        
this.words.add(word);
    }

    
@Override
    
protected Yuri clone(){
        
try{
            
return (Yuri) super.clone();
        }
catch (CloneNotSupportedException e){
            
return null;
        }
    }

    
@Override
    
public String toString() {
        
return "Yuri{" +
                
"name='" + name + '\'' +
                
", words=" + words.toString() +
                
'}';
    }
}
this

 

如上,重寫了clone()方法。在執行以下代碼時:spa

Yuri yuri = new Yuri();
yuri.setName(
"Yuri");
yuri.addWord(
"My name is Yuri");
yuri.addWord(
"You mind is clear");

Yuri yuri_copyer = yuri.clone();
yuri.setName(
"Yuri's copyer");設計

yuri.addWord("I'm not the only one true Yuri");orm



Log.
e("yuri_copyer",yuri_copyer.toString());
Log.
e("yuri",yuri.toString());對象

會驚奇地發現兩行Log如出一轍,這是由於這種原型模式的實現方式只拷貝其引用,換句話說就是並無將原型對象中的全部字段都從新構造一份,只是用複製對象的字段引用原型對象中的字段,所以被稱爲「淺拷貝」或「影子拷貝」。

 

(2)深拷貝

咱們把上文的clone()方法修改一下:

@Override
protected Yuri clone(){
    
try{
        Yuri copyer = (Yuri)
super.clone();
        copyer.
name = this.name;
        copyer.
words = (ArrayList<String>)this.words.clone();
        
return copyer;
    }
catch (CloneNotSupportedException e){
        
return null;
    }
}

 

如上,這種實現方式調用了的clone()方法,這樣能夠保證副本被修改時不影響原始對象,所以被稱爲「深拷貝」,又叫作「保護性拷貝」。

 

Android源碼中的原型模式

 

1)ArrayList

嚴格來講ArrayList並不算是Android源碼中的類,但應該是Android開發者最經常使用的類,ArrayList的clone()代碼以下:

/**
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
 * elements themselves are not copied.)
 *
 * @return a clone of this <tt>ArrayList</tt> instance
 */
public Object clone() {
    
try {
        ArrayList<?> v = (ArrayList<?>)
super.clone();
        v.elementData = Arrays.
copyOf(elementData, size);
        v.
modCount = 0;
        
return v;
    }
catch (CloneNotSupportedException e) {
        
// this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

 

你們能夠看到size並無被clone,由於size是基礎類型而不是引用類型,因此不須要clone。細心的讀者能夠看到註釋裏面的「shallow copy」,但這其實是一個典型的深拷貝。

 

(3)Intent

Android系統加入Intent機制的意義在於大大下降了Android四大組件之間的耦合度。Intent的clone()代碼以下:

@Override
public Object clone() {
    
return new Intent(this);
}

 

/**
 * Copy constructor.
 */
public Intent(Intent o) {
    
this.mAction = o.mAction;
    
this.mData = o.mData;
    
this.mType = o.mType;
    
this.mPackage = o.mPackage;
    
this.mComponent = o.mComponent;
    
this.mFlags = o.mFlags;
    
this.mContentUserHint = o.mContentUserHint;
    
if (o.mCategories != null) {
        
this.mCategories = new ArraySet<String>(o.mCategories);
    }
    
if (o.mExtras != null) {
        
this.mExtras = new Bundle(o.mExtras);
    }
    
if (o.mSourceBounds != null) {
        
this.mSourceBounds = new Rect(o.mSourceBounds);
    }
    
if (o.mSelector != null) {
        
this.mSelector = new Intent(o.mSelector);
    }
    
if (o.mClipData != null) {
        
this.mClipData = new ClipData(o.mClipData);
    }
}

 

Intent的clone()內部並無調用super.clone(),而是調用了new Intent(this)。

 

Android開發中如何利用原型模式

 

(1)Object的clone()方法直接操做二進制流,效率很是高。在對象的初始化要消耗很是多的資源時,或者用new來實例化一個對象時須要很是繁瑣的數據準備或訪問權限時,可使用原型模式提升效率、避免消耗資源。

 

2)對深拷貝生成的副本進行修改不會影響原始對象。當一個對象會被不一樣對象用不一樣方式修改時,能夠用原型模式產生副本供調用者使用。

 

須要注意的幾個問題

 

(1)原型模式在clone()的時候不會從新執行構造函數,可能會出現問題。

 

(2)在某些對象構造很是簡單的狀況下,好比上文提到的Intent,從新new一個比clone()快,所以不要濫用原型模式


本系列其餘博客

 

【設計模式與Android】工廠方法模式——化工女神的工廠


【設計模式與Android】抽象工廠模式——嵌合體克隆工廠


【設計模式與Android】策略模式——錦囊裏的上策中策下策


【設計模式與Android】狀態模式——一我的的兩幅面孔


【設計模式與Android】責任鏈模式——曹瞞兵敗走華容

相關文章
相關標籤/搜索