Android中的原型模式

設(shè)計模式.png

定義

原型的是一種創(chuàng)建型的設(shè)計模式超棺,主用來創(chuàng)建的復(fù)雜的對象和構(gòu)建耗時的實例。通過克隆已有的對象來創(chuàng)建的新的對象,從而節(jié)省時間和內(nèi)存。通過克隆一個已經(jīng)存在的實例可以使我們的程序運(yùn)行的更高效笆呆。

原型模式UML.jpg

使用場景

(1)類初始化需要消化非常多的資源,這個資源包括數(shù)據(jù)粱挡、硬件資源等赠幕,通過原型拷貝避免這些消耗。
(2)通過new產(chǎn)生的一個對象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或者權(quán)限询筏,這時可以使用原型模式榕堰。
(3)一個對象需要提供給其他對象訪問,而且各個調(diào)用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調(diào)用者使用逆屡,即保護(hù)性拷貝圾旨。

如何實現(xiàn)

首先我們得實現(xiàn)Cloneable接口,復(fù)寫clone方法

    implements  Cloneable
    
    @Override
    protected User clone() {
        User user = null;
        try{
            user = (User)super.clone();
        } catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
        return user;
    }

我們需要注意魏蔗,clone這個方法不是Cloneable接口中的砍的,我們來看Cloneable的定義,是一個空的接口莺治。

 * @author  unascribed
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0
 */
public interface Cloneable {
}

那么clone是哪來的呢廓鞠,其實clone是Object中的方法,Cloneable是一個標(biāo)識接口谣旁,它表明這個類的對象是可以拷貝的床佳。如果沒有實現(xiàn)Cloneable接口卻調(diào)用了clone()函數(shù)將拋出異常。

淺拷貝和深拷貝

那么在實現(xiàn)clone方法的時候榄审,需要注意個問題砌们,像上面那樣,直接調(diào)用

user = (User)super.clone();

這樣只是簡單的拷貝了對象搁进,實際上并不是將原始文檔的所有字段都重新構(gòu)造了一份浪感,而是副本文檔的字段引用原始文檔的字段。我們需要自己賦值其成員變量拷获,尤其當(dāng)成員變量為引用型對象時篮撑,邊涉及到了淺拷貝和深拷貝的問題。

拷貝.png

那么什么是深拷貝呢匆瓜,如何做赢笨? 其實就是拷貝時,我們的引用對象也得拷貝驮吱,更有甚者茧妒,比如Android中的Intent的深拷貝直接是new一個。

那我們來看一下深拷貝的demo代碼:

    @Override
    public WordDocument clone() {
        try {
            WordDocument doc = (WordDocument) super.clone();
            doc.mText = this.mText;
            doc.mImages = (ArrayList<String>) this.mImages.clone();
            return doc;
        } catch (CloneNotSupportedException e) {

        }
        return null;
    }

應(yīng)用

那么原型模式左冬,在我們的Android中有什么經(jīng)典應(yīng)用呢桐筏。此時我打開了AndroidStudio,直接跳到了我們的Intenet源碼拇砰。

 *
 * <p>These are the possible flags that can be used in the Intent via
 * {@link #setFlags} and {@link #addFlags}.  See {@link #setFlags} for a list
 * of all possible flags.
 */
public class Intent implements Parcelable, Cloneable {
    
    ...
    @Override
    public Object clone() {
        return new Intent(this);
    }

    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是深度拷貝,而且是直接new一個的深度拷貝除破∧恋可見其設(shè)計初衷不是因為其不是為了解決構(gòu)建復(fù)雜對象的資源消耗問題。

總結(jié)

原型模式本質(zhì)上就是對象拷貝瑰枫,與 C++ 中的拷貝構(gòu)造函數(shù)有些類似踱葛,它們之間容易出現(xiàn)的問題也都是深拷貝、淺拷貝。使用原型模式可以解決構(gòu)建復(fù)雜對象的資源消耗問題尸诽,能夠在某些場景下提升創(chuàng)建對象的效率甥材。還有一個重要的途徑就是保護(hù)性拷貝,也就是某個對象對外可能是只讀的性含,為了防止外部對這個只讀對象修改洲赵,通常可以通過返回一個對象拷貝的形式實現(xiàn)只讀的限制胶滋。

優(yōu)點:原型模式是在內(nèi)存中二進(jìn)制流的拷貝板鬓,要比直接 new 一個對象性能好很多悲敷,特別是要在一個循環(huán)體內(nèi)產(chǎn)生大量的對象時究恤,原型模式可以更好滴體現(xiàn)其優(yōu)點。

缺點:這既是它的優(yōu)點也是缺點后德,直接在內(nèi)存中拷貝部宿,構(gòu)造函數(shù)是不會執(zhí)行的,在實際開發(fā)中應(yīng)該注意這個潛在問題瓢湃,優(yōu)點就是減少了約束理张,缺點也是減少了約束,需要大家在實際應(yīng)用是考慮绵患。


謝謝大家閱讀雾叭,如有幫助,來個喜歡或者關(guān)注吧落蝙!


本文作者:Anderson/Jerey_Jobs

簡書地址:[Anderson大碼渣][1]

github地址:[Jerey_Jobs][2]
[1]: http://www.reibang.com/users/016a5ba708a0/latest_articles
[2]: https://github.com/Jerey-Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末织狐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筏勒,更是在濱河造成了極大的恐慌移迫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件管行,死亡現(xiàn)場離奇詭異厨埋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捐顷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門荡陷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迅涮,你說我怎么就攤上這事废赞。” “怎么了逗柴?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵蛹头,是天一觀的道長。 經(jīng)常有香客問我,道長渣蜗,這世上最難降的妖魔是什么屠尊? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮耕拷,結(jié)果婚禮上讼昆,老公的妹妹穿的比我還像新娘。我一直安慰自己骚烧,他們只是感情好浸赫,可當(dāng)我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赃绊,像睡著了一般既峡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碧查,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天运敢,我揣著相機(jī)與錄音,去河邊找鬼忠售。 笑死传惠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的稻扬。 我是一名探鬼主播卦方,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泰佳!你這毒婦竟也來了盼砍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤乐纸,失蹤者是張志新(化名)和其女友劉穎衬廷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汽绢,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡吗跋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宁昭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跌宛。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖积仗,靈堂內(nèi)的尸體忽然破棺而出疆拘,到底是詐尸還是另有隱情,我是刑警寧澤寂曹,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布哎迄,位于F島的核電站回右,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏漱挚。R本人自食惡果不足惜翔烁,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旨涝。 院中可真熱鬧蹬屹,春花似錦、人聲如沸白华。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弧腥。三九已至厦取,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸟赫,已是汗流浹背蒜胖。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留抛蚤,地道東北人。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓寻狂,卻偏偏與公主長得像岁经,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蛇券,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,665評論 2 354

推薦閱讀更多精彩內(nèi)容