盤點 Android 你用着卻不必定知道的設計模式(上)

前言

當本身的編碼時間久了以後,會發現優秀的代碼,每每是遵循合理的設計模式進行開發的,這些代碼具有高內聚、低耦合的特性,可以在隨時變化的需求中,保持穩定性、靈活性。html

本文,是在 Android 代碼中去尋找「設計模式」的影子,並不會很詳細地展開各個模式的定義與應用。文中選取的例子都是儘可能簡單易懂的,主要讓你們知道平時原來本身也是用着各類設計模式,只是不知道名字而已,開始盤它!java

篇幅有限且網上優秀的書籍多,因此不要想着在這一篇文章弄清楚它們。注:本人水平有限,不對的地方,還請指出修正)。android

1、單例模式

記得曾經筆試時就考過寫出單例模式的實現方式:一、懶漢式(線程安全);二、餓漢式(DCL);三、靜態內部類;四、枚舉實現(最佳實現)。git

當某個對象的建立是比較耗時的,若是頻繁的建立與銷燬的話,對性能影響又大,既然沒有好的辦法優化,那就在內存中持有這個對象的惟一實例,減小內存佔用。github

值得注意的是:一、單例對象建立的線程安全問題;二、Android 中建立單例時,若是持有 Context 容易致使內存泄露,儘可能使用 Application Context。算法

例如 GlideImageLoader 圖片加載框架,正是採用單例模式,來獲取實例對象的。設計模式

一、Glide.with(context).load(imageUrl).into(imageView);
     
     二、ImageLoader.getInstance().displayImage(imageUrl,imageView);
複製代碼

2、Builder 模式

構建者模式把一個對象的建立與表示分離開了,也就是說構建的過程不一樣,會生產出不一樣的對象出來。同時 Builder 類,把具體產品的建立細節隱藏了,使得咱們不用關注產品具體是怎麼實現的。例如:咱們無需關注調用方法的順序,由於 Builder 類已經封裝好了調用的順序了。還有這種鏈式調用寫起來真的很爽!安全

最多見的就是咱們 Android 裏面的對話框的建立過程了,咱們經過 AlertDialog.Builder() 構建的過程當中,有沒有設置按鈕、標題、提示等,其實建立出來的對話框風格是不同的。markdown

一、new AlertDialog.Builder()
            .setTitle("title")
            .setMessage("message")
            .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    // do something
                }
            }).create();
            
    二、new StringBuilder().append("A").append("B").append("C").toString();
複製代碼

這裏介紹一個 Android Studio 的插件 —— Builder Generator,這個插件能夠省去手寫 Builder 的煩惱。app

3、工廠模式

有如下幾種:

  1. 簡單工廠:含靜態方法,也叫靜態工廠,多用 if...else 來作分支,去建立各個實例,方法內部若是建立的對象多的,會略顯臃腫
  2. 工廠模式:含抽象工廠、具體工廠、抽象產品、具體產品之分,符合「開閉原則」
  3. 抽象工廠模式:與工廠模式的區別,工廠模式建立單一產品,抽象工廠能建立多種產品,符合「開閉原則」

工廠類封裝好類的實例化過程,隱藏了對象實例化的具體參數,只需傳入要建立類的惟一標識,工廠類就能建立出指定的類。換句話說:我只告訴工廠我要什麼,工廠只負責生產,我負責使用,具體工廠怎麼生產,我就無論啦~

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;
        }
    }
    
    
    Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");
複製代碼

Retrofit 可添加 Gson 轉換(這裏體現了 Builder 模式 和工廠模式

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(API_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
複製代碼

4、策略模式

將算法單獨封裝起來,使之替換時,互不影響。

以前看過一篇文章說怎麼消除項目代碼中的 if...else ,運用策略模式,將每一個 if...else 裏面的方法各自封裝,來解決由於大量的 if...else 致使的類臃腫

例如:android 中的設置動畫的插值器,替換不一樣插值器,各不影響,並且效果不一樣

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

5、模版模式

在抽象類中,定義模版(抽象)方法,並在子類作具體的實現。其實就是咱們常常用的 BaseActivityBaseFragment 那套東西,show code~

BaseActivity 裏面保證模版方法,按照順序執行,同時子類必須實現父類定義的抽象方法,提升了複用性以及擴展性。

public abstract class BaseActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 一、獲取佈局id
            setContentView(getLayoutId());
            // 二、初始化 view
            initView();
            // 三、初始化數據
            initData();
        }
        
        public abstract int getLayoutId();
    
        public abstract void initView();
    
        public abstract void initData();
    }
複製代碼

6、適配器模式

適配器模式,能夠解決接口不兼容的問題,使得本不兼容的接口一塊兒工做。

舉例:港版 iPhone 的充電器是三孔插頭,但是如今房間只有二孔插頭,因此我得網上買個三孔轉二孔的轉換器(至關於適配器),這樣個人三孔充電器就能在二孔插座使用了。

咱們經常使用 ListView 使用的 Adapter ,用的就是適配器模式,Google 開發工程師,設計代碼的時候,考慮到 ListView 每一個 ItemView 有不一樣 UI爲了應對這種可變性,BaseAdapter 提供 getView() 方法,以保證最後輸出的統一爲 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;
        }
    }
複製代碼

7、觀察者模式

觀察者模式,多以一對多的形式依賴存在。多個觀察者同時監聽着被監聽的對象時,當被監聽的對象發生狀態變化時候,會通知全部觀察者更新。

如:郵件的訂閱功能,訂閱某個模塊,當這個模塊有新的內容更新,會給全部訂閱者發送郵件。

Android 中,觀察者模式使用的是比較頻繁的,例如:EventBusRxJava等。最熟悉的就是 AdapternotifyDataSetChanged() 方法了,你們能夠點進去看源碼,當數據發生改變的時候,通知 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();
    }
複製代碼

推薦閱讀

相關文章
相關標籤/搜索