盤點(diǎn) Android 你用著卻不一定知道的設(shè)計(jì)模式(上)

盤點(diǎn) Android 你用著卻不一定知道的設(shè)計(jì)模式

前言

當(dāng)自己的編碼時(shí)間久了之后涩赢,會(huì)發(fā)現(xiàn)優(yōu)秀的代碼,往往是遵循合理的設(shè)計(jì)模式進(jìn)行開發(fā)的轰胁,這些代碼具備高內(nèi)聚谒主、低耦合的特性,能夠在隨時(shí)變化的需求中赃阀,保持穩(wěn)定性霎肯、靈活性。

本文榛斯,是在 Android 代碼中去尋找「設(shè)計(jì)模式」的影子观游,并不會(huì)很詳細(xì)地展開各個(gè)模式的定義與應(yīng)用。文中選取的例子都是盡量簡(jiǎn)單易懂的驮俗,主要讓大家知道平時(shí)原來(lái)自己也是用著各種設(shè)計(jì)模式懂缕,只是不知道名字而已,開始盤它王凑!

篇幅有限且網(wǎng)上優(yōu)秀的書籍多搪柑,所以不要想著在這一篇文章弄清楚它們聋丝。注:本人水平有限,不對(duì)的地方工碾,還請(qǐng)指出修正)弱睦。

一、單例模式

記得曾經(jīng)筆試時(shí)就考過寫出單例模式的實(shí)現(xiàn)方式:1渊额、懶漢式(線程安全)况木;2、餓漢式(DCL)旬迹;3火惊、靜態(tài)內(nèi)部類;4奔垦、枚舉實(shí)現(xiàn)(最佳實(shí)現(xiàn))屹耐。

當(dāng)某個(gè)對(duì)象的創(chuàng)建是比較耗時(shí)的,如果頻繁的創(chuàng)建與銷毀的話椿猎,對(duì)性能影響又大张症,既然沒有好的辦法優(yōu)化,那就在內(nèi)存中持有這個(gè)對(duì)象的唯一實(shí)例鸵贬,減少內(nèi)存占用俗他。

值得注意的是:1、單例對(duì)象創(chuàng)建的線程安全問題阔逼;2兆衅、Android 中創(chuàng)建單例時(shí),如果持有 Context 容易導(dǎo)致內(nèi)存泄露嗜浮,盡量使用 Application Context羡亩。

例如 GlideImageLoader 圖片加載框架危融,正是采用單例模式畏铆,來(lái)獲取實(shí)例對(duì)象的。

     1吉殃、Glide.with(context).load(imageUrl).into(imageView);
     
     2辞居、ImageLoader.getInstance().displayImage(imageUrl,imageView);

二、Builder 模式

構(gòu)建者模式把一個(gè)對(duì)象的創(chuàng)建與表示分離開了蛋勺,也就是說構(gòu)建的過程不同瓦灶,會(huì)生產(chǎn)出不同的對(duì)象出來(lái)。同時(shí) Builder 類抱完,把具體產(chǎn)品的創(chuàng)建細(xì)節(jié)隱藏了贼陶,使得我們不用關(guān)注產(chǎn)品具體是怎么實(shí)現(xiàn)的。例如:我們無(wú)需關(guān)注調(diào)用方法的順序,因?yàn)?Builder 類已經(jīng)封裝好了調(diào)用的順序了碉怔。還有這種鏈?zhǔn)秸{(diào)用寫起來(lái)真的很爽烘贴!

最常見的就是我們 Android 里面的對(duì)話框的創(chuàng)建過程了,我們通過 AlertDialog.Builder() 構(gòu)建的過程中撮胧,有沒有設(shè)置按鈕庙楚、標(biāo)題、提示等趴樱,其實(shí)創(chuàng)建出來(lái)的對(duì)話框風(fēng)格是不一樣的。

    1酪捡、new AlertDialog.Builder()
            .setTitle("title")
            .setMessage("message")
            .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    // do something
                }
            }).create();
            
    2叁征、new StringBuilder().append("A").append("B").append("C").toString();

這里介紹一個(gè) Android Studio 的插件 —— Builder Generator,這個(gè)插件可以省去手寫 Builder 的煩惱逛薇。

三捺疼、工廠模式

有以下幾種:

  1. 簡(jiǎn)單工廠:含靜態(tài)方法,也叫靜態(tài)工廠永罚,多用 if...else 來(lái)做分支啤呼,去創(chuàng)建各個(gè)實(shí)例,方法內(nèi)部如果創(chuàng)建的對(duì)象多的呢袱,會(huì)略顯臃腫
  2. 工廠模式:含抽象工廠官扣、具體工廠、抽象產(chǎn)品羞福、具體產(chǎn)品之分惕蹄,符合“開閉原則”
  3. 抽象工廠模式:與工廠模式的區(qū)別,工廠模式創(chuàng)建單一產(chǎn)品治专,抽象工廠能創(chuàng)建多種產(chǎn)品卖陵,符合“開閉原則”

工廠類封裝好類的實(shí)例化過程,隱藏了對(duì)象實(shí)例化的具體參數(shù)张峰,只需傳入要?jiǎng)?chuàng)建類的唯一標(biāo)識(shí)泪蔫,工廠類就能創(chuàng)建出指定的類。換句話說:我只告訴工廠我要什么喘批,工廠只負(fù)責(zé)生產(chǎn)撩荣,我負(fù)責(zé)使用,具體工廠怎么生產(chǎn)饶深,我就不管啦~

    public class ConcreteFactory extends Factory {
        public <T extends Product> T createProduct(Class<T> c){
            Product product=null;
            try {
                product = (Product)Class.forName(c.getName()).newInstance();
            } catch (Exception e) {
                //異常處理
            }
            return (T)product;
        }
    }

Retrofit 可添加 Gson 轉(zhuǎn)換(這里體現(xiàn)了 Builder 模式 和工廠模式

    Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(API_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

四婿滓、策略模式

將算法單獨(dú)封裝起來(lái),使之替換時(shí)粥喜,互不影響凸主。

之前看過一篇文章說怎么消除項(xiàng)目代碼中的 if...else ,運(yùn)用策略模式额湘,將每個(gè) if...else 里面的方法各自封裝卿吐,來(lái)解決因?yàn)榇罅康?if...else 導(dǎo)致的類臃腫旁舰。

例如:android 中的設(shè)置動(dòng)畫的插值器,替換不同插值器嗡官,各不影響箭窜,而且效果不同

    Animation animation = new AlphaAnimation(1,0);
    animation.setInterpolator(new AccelerateDecelerateInterpolator());
    imageView.setAnimation(animation);
    animation.start();

五、模版模式

在抽象類中衍腥,定義模版(抽象)方法磺樱,并在子類做具體的實(shí)現(xiàn)。其實(shí)就是我們經(jīng)常用的 BaseActivity 婆咸、BaseFragment 那套東西竹捉,show code~

BaseActivity 里面保證模版方法,按照順序執(zhí)行尚骄,同時(shí)子類必須實(shí)現(xiàn)父類定義的抽象方法块差,提高了復(fù)用性以及擴(kuò)展性。

    public abstract class BaseActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 1倔丈、獲取布局id
            setContentView(getLayoutId());
            // 2憨闰、初始化 view
            initView();
            // 3、初始化數(shù)據(jù)
            initData();
        }
        
        public abstract int getLayoutId();
    
        public abstract void initView();
    
        public abstract void initData();
    }

五需五、適配器模式

適配器模式鹉动,可以解決接口不兼容的問題,使得本不兼容的接口一起工作宏邮。

舉例:港版 iPhone 的充電器是三孔插頭训裆,可是現(xiàn)在房間只有二孔插頭,所以我得網(wǎng)上買個(gè)三孔轉(zhuǎn)二孔的轉(zhuǎn)換器(相當(dāng)于適配器)蜀铲,這樣我的三孔充電器就能在二孔插座使用了边琉。

我們常用 ListView 使用的 Adapter ,用的就是適配器模式记劝,Google 開發(fā)工程師变姨,設(shè)計(jì)代碼的時(shí)候,考慮到 ListView 每個(gè) ItemView 有不同 UI厌丑。為了應(yīng)對(duì)這種可變性定欧,BaseAdapter 提供 getView() 方法,以保證最后輸出的統(tǒng)一為 View怒竿。

    public class MyAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return 0;
        }
    
        @Override
        public Object getItem(int position) {
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return null;
        }
    }

六砍鸠、觀察者模式

觀察者模式,多以一對(duì)多的形式依賴存在耕驰。多個(gè)觀察者同時(shí)監(jiān)聽著被監(jiān)聽的對(duì)象時(shí)爷辱,當(dāng)被監(jiān)聽的對(duì)象發(fā)生狀態(tài)變化時(shí)候,會(huì)通知所有觀察者更新。

如:郵件的訂閱功能饭弓,訂閱某個(gè)模塊双饥,當(dāng)這個(gè)模塊有新的內(nèi)容更新,會(huì)給所有訂閱者發(fā)送郵件弟断。

Android 中咏花,觀察者模式使用的是比較頻繁的,例如:EventBus阀趴、RxJava等昏翰。最熟悉的就是 AdapternotifyDataSetChanged() 方法了,大家可以點(diǎn)進(jìn)去看源碼刘急,當(dāng)數(shù)據(jù)發(fā)生改變的時(shí)候棚菊,通知 itemView 重新布局。

   /**
   * 觀察者集合
   */
   private final DataSetObservable mDataSetObservable = new DataSetObservable();
   
   //此處排霉,省略很多代碼...
   
    /**
     * Notifies the attached observers that the underlying data has been changed
     * and any View reflecting the data set should refresh itself.
     */
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

推薦閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市民轴,隨后出現(xiàn)的幾起案子攻柠,更是在濱河造成了極大的恐慌,老刑警劉巖后裸,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑰钮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡微驶,警方通過查閱死者的電腦和手機(jī)浪谴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)因苹,“玉大人苟耻,你說我怎么就攤上這事》鲩埽” “怎么了凶杖?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)款筑。 經(jīng)常有香客問我智蝠,道長(zhǎng),這世上最難降的妖魔是什么奈梳? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任杈湾,我火速辦了婚禮,結(jié)果婚禮上攘须,老公的妹妹穿的比我還像新娘漆撞。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布叫挟。 她就那樣靜靜地躺著艰匙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抹恳。 梳的紋絲不亂的頭發(fā)上员凝,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音奋献,去河邊找鬼健霹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瓶蚂,可吹牛的內(nèi)容都是我干的糖埋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窃这,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞳别!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起杭攻,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祟敛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兆解,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馆铁,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锅睛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了埠巨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡现拒,死狀恐怖辣垒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情印蔬,我是刑警寧澤乍构,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站扛点,受9級(jí)特大地震影響哥遮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陵究,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一眠饮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铜邮,春花似錦仪召、人聲如沸寨蹋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)已旧。三九已至,卻和暖如春召娜,著一層夾襖步出監(jiān)牢的瞬間运褪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工玖瘸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秸讹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓雅倒,卻偏偏與公主長(zhǎng)得像璃诀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔑匣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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