走向面向?qū)ο蟮牧笤瓌t——單一職責(zé)原則

寫在前面#


新的主題確定了,這一次準(zhǔn)備總結(jié)Android設(shè)計(jì)模式,其實(shí)更準(zhǔn)確的說應(yīng)該叫做JAVA設(shè)計(jì)模式,這注定是一個(gè)浩大的工程,有你們陪著,我很快樂。

面向?qū)ο缶幊痰牧笤瓌t


優(yōu)化代碼的第一步,單一職責(zé)原則###

單一職責(zé)原則的英文名稱是Single Responsibility Principle,縮寫是SRP。它的定義是:就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。簡(jiǎn)單來(lái)說,一個(gè)類應(yīng)該是一組相關(guān)性非常高的函數(shù)、數(shù)據(jù)的封裝
我們通過一個(gè)實(shí)際的Android例子進(jìn)行講解。

相信很多同學(xué)在學(xué)習(xí)安卓的過程中都有嘗試寫一個(gè)屬于自己的ImageLoader,那么通常新手所做的ImageLoader應(yīng)該是什么樣呢?

public class ImageLoader {    
    // 圖片緩存    
    LruCache<String, Bitmap> mImageCache;    
    // 線程池,線程數(shù)為CPU所允許的數(shù)量    
    ExecutorService mExecutorService =     Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 
    public ImageLoader() {    
        initImageCache();
    }   
    private void initImageCache() {        
        // 獲取APP可使用的最大內(nèi)存       
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);        
        // 獲取四分之一大小作為緩存空間          
        int cacheMemorySize = maxMemory / 4;        
        mImageCache = new LruCache<String, Bitmap>(cacheMemorySize) {      
            //Sizeof方法的作用只要是定義緩存中每項(xiàng)的大小,當(dāng)我們緩存進(jìn)去一個(gè)數(shù)據(jù)后,     
            //當(dāng)前已緩存的Size就會(huì)根據(jù)這個(gè)方法將當(dāng)前加進(jìn)來(lái)的數(shù)據(jù)也加上,便于統(tǒng)計(jì)當(dāng)    
            // 前使用了多少內(nèi)存,如果已使用的大小超過maxSize就會(huì)進(jìn)行清除動(dòng)作;           
             @Override            
            protected int sizeOf(String key, Bitmap bitmap) {                
                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;            
            }        
        };    
    }    
    public void displayImg(final String url, final ImageView imageView) {
        Bitmap bitmap = mImageCache.get(url);
        if (bitmap != null) {    imageView.setImageBitmap(bitmap);    return;
    }        
        // View中的setTag(object)表示給View添加一個(gè)格外的數(shù)據(jù),以后可以用getTag()將這個(gè)數(shù)據(jù)取出來(lái)。        
        imageView.setTag(url);        
        //在子線程中完成加載圖片和緩存圖片        
        mExecutorService.submit(new Runnable() {            
            @Override            
            public void run() {                
                Bitmap bitmap = downloadImg(url);                
                if (bitmap == null) return;                
                if (imageView.getTag().equals(url)) {                    
                    imageView.setImageBitmap(bitmap);               
                }                
                mImageCache.put(url, bitmap);           
             }        
        });    
    }    
    private Bitmap downloadImg(String imageUrl) {        
        Bitmap bitmap = null;        
        try {            
            URL url = new URL(imageUrl);            
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();            
            bitmap = BitmapFactory.decodeStream(connection.getInputStream());            
            connection.disconnect();        
        } catch (MalformedURLException e) {            
            e.printStackTrace();        
        } catch (IOException e) {           
            e.printStackTrace();        
        }        
            return bitmap;    
        }
   }

稍微懂一些的朋友就要說了,這樣的代碼耦合性太強(qiáng)了,簡(jiǎn)直沒有設(shè)計(jì)可言,更不要說拓展性和靈活性了,隨著ImageLoader功能的增多,ImageLoader會(huì)越來(lái)越大,代碼越來(lái)越復(fù)雜,圖片加載系統(tǒng)就越來(lái)越脆弱了!那么,作為一個(gè)新手,該怎么改進(jìn)呢?

public class ImageLoader {
    // 圖片緩存
    ImageCache mImageCache = new ImageCache();
    // 線程池,線程數(shù)為CPU所允許的數(shù)量
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    public void displayImg(final String url, final ImageView imageView) {
        Bitmap bitmap = mImageCache.get(url);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
            return;
        }
        // View中的setTag(object)表示給View添加一個(gè)格外的數(shù)據(jù),以后可以用getTag()將這個(gè)數(shù)據(jù)取出來(lái)。
        imageView.setTag(url);
        //在子線程中完成加載圖片和緩存圖片
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downloadImg(url);
                if (bitmap == null) return;
                if (imageView.getTag().equals(url)) {
                    imageView.setImageBitmap(bitmap);
                }
                mImageCache.put(url, bitmap);
            }
        });
    }
    private Bitmap downloadImg(String imageUrl) {
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            bitmap = BitmapFactory.decodeStream(connection.getInputStream());
            connection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }}

public class ImageCache {
    // 圖片緩存
    LruCache<String, Bitmap> mImageCache;

    public ImageCache() {
        initImageCache();
    }

    private void initImageCache() {
    // 獲取APP可使用的最大內(nèi)存
    int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    // 獲取四分之一大小作為緩存空間
    int cacheMemorySize = maxMemory / 4;
    mImageCache = new LruCache<String, Bitmap>(cacheMemorySize) {
        /**
         * Sizeof方法的作用只要是定義緩存中每項(xiàng)的大小,當(dāng)我們緩存進(jìn)去一個(gè)數(shù)據(jù)后,
         * 當(dāng)前已緩存的Size就會(huì)根據(jù)這個(gè)方法將當(dāng)前加進(jìn)來(lái)的數(shù)據(jù)也加上,便于統(tǒng)計(jì)當(dāng)
         * 前使用了多少內(nèi)存,如果已使用的大小超過maxSize就會(huì)進(jìn)行清除動(dòng)作;
         */
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
            }
        };
    }

    public void put(String url, Bitmap bitmap) {
        mImageCache.put(url, bitmap);
    }

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

如上述代碼所示,將一個(gè)ImageLoader拆分成了兩個(gè),ImageLoader只負(fù)責(zé)圖片加載的邏輯,而ImageCache只負(fù)責(zé)處理圖片緩存。這樣一來(lái)ImageLoader的代碼變少了,邏輯也清晰了;當(dāng)緩存邏輯需要修改時(shí),就不需要再改變ImageLoader中的代碼了。
從上述的例子中我們可以看出,單一職責(zé)原則的關(guān)鍵就在于單一二字,正如上文所述,一個(gè)類應(yīng)該是一組相關(guān)性非常高的函數(shù)、數(shù)據(jù)的封裝。每個(gè)人根據(jù)自己的經(jīng)驗(yàn),看法和具體的業(yè)務(wù)邏輯去劃分職責(zé),個(gè)性很強(qiáng)。但是,它也有一些基本的知道原則。比如兩個(gè)完全不一樣的功能就不應(yīng)該放在一個(gè)類之內(nèi)。
一個(gè)類應(yīng)該是一組相關(guān)性非常高的函數(shù)、數(shù)據(jù)的封裝。工程師可以不斷審視自己的代碼,根據(jù)具體的業(yè)務(wù)、功能對(duì)類進(jìn)行對(duì)應(yīng)的拆分,這是程序優(yōu)化邁出的第一步!這也是為什么會(huì)有MVC,MVP等各種設(shè)計(jì)模式出現(xiàn)的原因!


希望閱讀本章內(nèi)容之后你能夠有所收獲!感謝閱讀與喜歡!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370

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