編輯:關於Android編程
用原型實例指定創建對象的種類,並通過拷貝這些原型創建新的對象。
1、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等,通過原型拷貝避免這些消耗;
2、通過 new 產生一個對象需要非常繁瑣的數據准備或訪問權限,則可以使用原型模式;
3、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用,即保護性拷貝。
Client : 客戶端用戶。
Prototype : 抽象類或者接口,聲明具備clone能力。
ConcretePrototype : 具體的原型類.
下面我們以簡單的文檔拷貝為例來演示一下簡單的原型模式模式。
package com.dp.example.builder; package com.dp.example.prototype; import java.util.ArrayList; import java.util.List; /** * 文檔類型, 扮演的是ConcretePrototype角色,而cloneable是代表prototype角色 * * @author mrsimple */ public class WordDocument implements Cloneable { /** * 文本 */ private String mText; /** * 圖片名列表 */ private ArrayListmImages = new ArrayList (); public WordDocument() { System.out.println("----------- WordDocument構造函數 -----------"); } /** * 克隆對象 */ @Override protected WordDocument clone() { try { WordDocument doc = (WordDocument) super.clone(); doc.mText = this.mText; doc.mImages = this.mImages; return doc; } catch (Exception e) { } return null; } public String getText() { return mText; } public void setText(String mText) { this.mText = mText; } public List getImages() { return mImages; } /** * @param img */ public void addImage(String img) { this.mImages.add(img); } /** * 打印文檔內容 */ public void showDocument() { System.out.println("----------- Word Content Start -----------"); System.out.println("Text : " + mText); System.out.println("Images List: "); for (String imgName : mImages) { System.out.println("image name : " + imgName); } System.out.println("----------- Word Content End -----------"); } }
通過WordDocument類模擬了word文檔中的基本元素,即文字和圖片。WordDocument的在該原型模式示例中扮演的角色為ConcretePrototype, 而Cloneable的角色則為Prototype。WordDocument實現了clone方法以實現對象克隆。下面我們看看Client端的使用 :
public class Client { public static void main(String[] args) { WordDocument originDoc = new WordDocument(); originDoc.setText("這是一篇文檔"); originDoc.addImage("圖片1"); originDoc.addImage("圖片2"); originDoc.addImage("圖片3"); originDoc.showDocument(); WordDocument doc2 = originDoc.clone(); doc2.showDocument(); doc2.setText("這是修改過的Doc2文本"); doc2.showDocument(); originDoc.showDocument(); } }
輸出結果如下 :
可以看到,doc2是通過originDoc.clone()創建的,並且doc2第一次輸出的時候和originDoc輸出是一樣的。即doc2是originDoc的一份拷貝,他們的內容是一樣的,而doc2修改了文本內容以後並不會影響originDoc的文本內容。需要注意的是通過clone拷貝對象的時候並不會執行構造函數!
將main函數的內容修改為如下 :
public static void main(String[] args) { WordDocument originDoc = new WordDocument(); originDoc.setText("這是一篇文檔"); originDoc.addImage("圖片1"); originDoc.addImage("圖片2"); originDoc.addImage("圖片3"); originDoc.showDocument(); WordDocument doc2 = originDoc.clone(); doc2.showDocument(); doc2.setText("這是修改過的Doc2文本"); doc2.addImage("哈哈.jpg"); doc2.showDocument(); originDoc.showDocument(); }
細心的朋友可能發現了,在doc2添加了一張名為"哈哈.jpg"的照片,但是卻也顯示在originDoc中?這是怎麼回事呢? 其實學習過C++的朋友都知道,這是因為上文中WordDocument的clone方法中只是簡單的進行淺拷貝,引用類型的新對象doc2的mImages只是單純的指向了this.mImages引用,而並沒有進行拷貝。doc2的mImages添加了新的圖片,實際上也就是往originDoc裡添加了新的圖片,所以originDoc裡面也有"哈哈.jpg" 。那如何解決這個問題呢? 那就是采用深拷貝,即在拷貝對象時,對於引用型的字段也要采用拷貝的形式,而不是單純引用的形式。示例如下 :
/** * 克隆對象 */ @Override protected WordDocument clone() { try { WordDocument doc = (WordDocument) super.clone(); doc.mText = this.mText; // doc.mImages = this.mImages; doc.mImages = (ArrayList如上代碼所示,將doc.mImages指向this.mImages的一份拷貝, 而不是this.mImages本身,這樣在doc2添加圖片時並不會影響originDoc,如圖所示 :) this.mImages.clone(); return doc; } catch (Exception e) { } return null; }
在Android源碼中,我們以熟悉的Intent來分析源碼中的原型模式。簡單示例如下 :
Uri uri = Uri.parse("smsto:0800000123"); Intent shareIntent = new Intent(Intent.ACTION_SENDTO, uri); shareIntent.putExtra("sms_body", "The SMS text"); Intent intent = (Intent)shareIntent.clone() ; startActivity(intent);
結果如下 :
可以看到,我們通過shareIntent.clone方法拷貝了一個對象intent, 然後執行startActivity(intent), 隨即就進入了短信頁面,號碼為0800000123,文本內容為The SMS text,即這些內容都與shareIntent一致。
下面我們看看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; if (o.mCategories != null) { this.mCategories = new ArraySet可以看到,clone方法實際上在內部調用了new Intent(this); 這就和C++中的拷貝構造函數完全一致了,而且是深拷貝。由於該模式比較簡單,就不做太多說明。(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); } }
一、stitching_detail程序運行流程1.命令行調用程序,輸入源圖像以及程序的參數2.特征點檢測,判斷是使用surf還是orb,默認是surf。3.對圖像的特征
屬性動畫屬性動畫的核心主要是ObjectAnimator,ValueAnimator這幾個對象的使用。下面對各個方法的使用進行介紹。ObjectAnimator的使用:一
現在市面上的很多的應用,都帶有下拉列表的功能,將所有選項都放在下拉列表中,當用戶點擊選擇的時候,彈出所有的選項,用戶選擇一項後,下拉列表自動隱藏,很多下拉列表都是用Lis
業余時間充足,於是想弄點自己的東西,找來找去還是回到當初感興趣的VR。目前好像沒有太多關於VR方面的教程,於是有了寫‘學習筆記’的想法。說干就干~