我的理解:開閉原則

定義:一個軟件實體如類零渐、模塊和函數(shù)應該對擴展開放窒舟,對修改關(guān)閉。
也就是說相恃,如果修改或者添加一個功能辜纲,應該是通過擴展原來的代碼笨觅,而不是通過修改原來的代碼拦耐。

比如,在圖片加載類中见剩,有內(nèi)存緩存杀糯,磁盤緩存,還有雙緩存:

//內(nèi)存緩存
public class MemoryCache {

    LruCache<String, Bitmap> mLruCache;

    public MemoryCache() {
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        int cacheSize = maxMemory / 4;
        mLruCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight() / 1024;
            }
        };
    }

    public Bitmap get(String url) {
        return return mLruCache.get(url);
    }

    public void put(String url, Bitmap bmp) {
        // do something
    }
}

//磁盤緩存
public class DiskCache {
    public Bitmap get(String url) {
        return BitmapFactory.decodeFile(url);
    }

    public void put(String url, Bitmap bmp) {
       //do something
    }
}

//雙緩存
public class DoubleCache {
    MemoryCache mMemoryCache = new MemoryCache();
    DiskCache mDiskCache = new DiskCache();

    public Bitmap get(String url) {
        Bitmap bitmap = mMemoryCache.get(url);
        if (bitmap==null){
            bitmap = mDiskCache.get(url);
        }
        return bitmap;
    }

    public void put(String url, Bitmap bmp) {
        //do something
    }
}

如果不用開閉原則苍苞,那么在圖片加載類中固翰,可能會這么寫:

public class ImageLoader {

    MemoryCache mMemoryCache = new MemoryCache();
    DiskCache mDiskCache = new DiskCache();
    DoubleCache mDoubleCache = new DoubleCache();

    boolean isDiskCache = false; //使用磁盤緩存
    boolean isDoubleCache = false; //使用雙緩存

    public ImageLoader() {
    }

    public void displayImage(String url, ImageView mImageView) {
        Bitmap bitmap = null;
        if (isDoubleCache) {
            bitmap = mDoubleCache.get(url);
        } else if (isDiskCache) {
            bitmap = mDiskCache.get(url);
        } else {
            bitmap = mMemoryCache.get(url);
        }
        if (bitmap != null) {
            mImageView.setImageBitmap(bitmap);
        } else {
            //沒有緩存,下載圖片
        }
    }

    public void setDiskCache(boolean diskCache) {
        isDiskCache = diskCache;
    }

    public void setDoubleCache(boolean doubleCache) {
        isDoubleCache = doubleCache;
    }
}

這樣寫羹呵,可能會出現(xiàn)這樣的問題:
if-else 的判斷條件太多骂际,如果寫錯了其中一個,就會化很多時間去查找和解決冈欢,ImageLoader 類也會變得臃腫歉铝,而且用戶不能自己實現(xiàn)緩存注入到 ImageLoader 中,可擴展性差凑耻。

那么太示,通過分析可以知道,每個緩存都用 set 和 put 方法香浩,那么可以把它抽象出來类缤。
UML圖:

UML

這樣通過接口就可以實現(xiàn)不同的緩存,而且不需要改變 ImageLoader 的代碼邻吭。

首先創(chuàng)建接口 ImageCache:

public interface ImageCache {
    void put(String url, Bitmap bmp);
    Bitmap get(String url);
}

然后將原來的三種緩存都繼承它:

//內(nèi)存緩存
public class MemoryCache implements ImageCache {

    LruCache<String, Bitmap> mLruCache;

    public MemoryCache() {
        //初始化LruCache
    }

    @Override
    public void put(String url, Bitmap bmp) {
        mLruCache.put(url, bmp);
    }

    @Override
    public Bitmap get(String url) {
        return mLruCache.get(url);
    }
}

//磁盤緩存
public class DiskCache implements ImageCache{

    @Override
    public void put(String url, Bitmap bmp) {
        //將Bitmap寫入文件
    }

    @Override
    public Bitmap get(String url) {
       return BitmapFactory.decodeFile(url); //從文件中獲取Bitmap
    }
}

//雙緩存
public class DoubleCache implements ImageCache {
    ImageCache mMemoryCache = new MemoryCache();
    ImageCache mDiskCache = new DiskCache();

    @Override
    public void put(String url, Bitmap bmp) {
        mMemoryCache.put(url, bmp);
        mDiskCache.put(url, bmp);
    }

    @Override
    public Bitmap get(String url) {
        Bitmap bitmap = mMemoryCache.get(url);
        if (bitmap == null) {
            bitmap = mDiskCache.get(url);
        }
        return bitmap;
    }
}

那么餐弱,ImageLoader 類就可以改寫成:

public class ImageLoader {

    ImageCache mImageCache = new MemoryCache();

    public void setImageCache(ImageCache imageCache) {
        mImageCache = imageCache;
    }

    public ImageLoader() {
    }

    public void displayImage(String url, ImageView mImageView) {
        Bitmap bitmap = mImageCache.get(url);
        if (bitmap != null) {
            mImageView.setImageBitmap(bitmap);
        }
        //圖片沒緩存,下載
        // do something
    }
}

比原來的簡潔很多囱晴。

那么在使用的時候這樣:

ImageLoader imageLoader = new ImageLoader();
//選擇使用內(nèi)存緩存
imageLoader.setImageCache(new MemoryCache());
//選擇使用磁盤緩存
imageLoader.setImageCache(new DiskCache());
//選擇使用雙緩存
imageLoader.setImageCache(new DoubleCache());
//不選擇封裝好的緩存膏蚓,自己實現(xiàn)緩存
imageLoader.setImageCache(new ImageCache() {
    @Override
    public void put(String url, Bitmap bmp) {

    }

    @Override
    public Bitmap get(String url) {
        return null;
    }
});

可以看到,用戶通過 setImageCache 方法可以自由設(shè)置緩存的實現(xiàn)方式速缆,而不用通過修改 ImageLoader 來實現(xiàn)降允。setImageCache 就是通常說的依賴注入。使得 ImageLoader 類更加健壯艺糜,這就是開閉原則剧董。

這里幢尚,應該明白開閉原則是怎么一回事了。

參考:《Android源碼設(shè)計模式解析與實踐》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翅楼,一起剝皮案震驚了整個濱河市尉剩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毅臊,老刑警劉巖理茎,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異管嬉,居然都是意外死亡,警方通過查閱死者的電腦和手機础倍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門德迹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事芽腾√希” “怎么了眨八?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵篓足,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么砾赔? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任专普,我火速辦了婚禮檀夹,結(jié)果婚禮上筋粗,老公的妹妹穿的比我還像新娘。我一直安慰自己炸渡,他們只是感情好娜亿,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚌堵,像睡著了一般买决。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吼畏,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天督赤,我揣著相機與錄音,去河邊找鬼泻蚊。 笑死躲舌,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的性雄。 我是一名探鬼主播没卸,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼枯冈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了办悟?” 一聲冷哼從身側(cè)響起尘奏,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎病蛉,沒想到半個月后炫加,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡铺然,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年俗孝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魄健。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡赋铝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沽瘦,到底是詐尸還是另有隱情革骨,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布析恋,位于F島的核電站良哲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏助隧。R本人自食惡果不足惜筑凫,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望并村。 院中可真熱鬧巍实,春花似錦、人聲如沸哩牍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姐叁。三九已至瓦盛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間外潜,已是汗流浹背原环。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留处窥,地道東北人嘱吗。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谒麦。 傳聞我的和親對象是個殘疾皇子俄讹,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

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

  • 本文出自《Android源碼設(shè)計模式解析與實戰(zhàn)》中的第一章。 1绕德、優(yōu)化代碼的第一步——單一職責原則 單一職責原則的...
    MrSimp1e0閱讀 1,766評論 1 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,081評論 25 707
  • 最新在閱讀《Android源碼設(shè)計模式解析與實戰(zhàn)》一書患膛,我覺得寫的很清晰,每一個知識點都有示例耻蛇,通過示例更加容易理...
    慕涵盛華閱讀 1,944評論 0 3
  • 昨天發(fā)布的2017胡潤全球富豪榜中踪蹬,在全球十億美金富豪里,女性占比15%臣咖,其中121位來自中國跃捣。同樣的,創(chuàng)業(yè)邦用2...
    JulienYu閱讀 1,828評論 5 10
  • 01給你舞臺并不是一定要你跳舞 其實今天一共四個部分夺蛇,有兩個部分是不愉快的事件引發(fā)的疚漆。首先第一個的故事是這樣的,我...
    JeffreyShu閱讀 187評論 0 0