面向?qū)ο蟮牧笤瓌t之單一職責原則

單一職責原則(SRP)又稱單一功能原則,為面向?qū)ο罅蠡驹瓌t之一。

我們先來看一下官方是如何描述該原則的:

? ? ? ?該原則是由羅伯特·C·馬丁于《敏捷軟件開發(fā):原則、模式和實踐》一書中給出。它規(guī)定一個類只應(yīng)該只有一個發(fā)生變化的原因。所謂職責是指類變化的原因,如果一個類有多于一個的動機被改變,那么這個類就具有多于一個的職責,而單一職責原則就是指一個類或者模塊應(yīng)該只有一個改變的原因。

? ? ? ?這樣解釋單一職責原則恐怕比較難以理解,我們可先通過實現(xiàn)一個圖片加載器,并且將圖片緩存起來的需求的例子來理解一下單一職責原則。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;
import android.widget.ImageView;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import retrofit2.http.Url;

/**
 * 圖片加載類
 */
public class ImageLoader {
    LruCache<String, Bitmap> mImageCache;
    //線程池,線程數(shù)量為CPU的數(shù)量
    ExecutorService mExecutorService= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    public ImageLoader(){
          initImageCache();
    }

    private void initImageCache()
    {
        //計算可以使用的最大內(nèi)存
        final int maxMemory= (int) (Runtime.getRuntime().maxMemory()/1024);
        //取可用內(nèi)存的1/4
        final int cachesize=maxMemory/4;
        mImageCache=new LruCache<String,Bitmap>(cachesize){
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getRowBytes()*bitmap.getHeight()/1024;
            }  
       };
    }

    /**
     * 將下載的Bitmap對象顯示在Imageview上
     * @param url
     * @param imageView
     */
    public void displayBitmap(final String url, final ImageView imageView){
        imageView.setTag(url);
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
               Bitmap bitmap=downBitmap(url);
               if(bitmap==null)
               {
                   return;
               }
               if(imageView.getTag().equals(url))
               {
                   imageView.setImageBitmap(bitmap);
               }
                   mImageCache.put(url,bitmap);
            }
        });
    }

    /**
     * 通過URL下載圖片,并返回Bitmap
     * @param imageUrl
     * @return
     */
    public Bitmap downBitmap(String imageUrl)
    {
        Bitmap bitmap=null;
        try{
            URL url=new URL(imageUrl);
            final HttpURLConnection connection= (HttpURLConnection) url.openConnection();
            bitmap= BitmapFactory.decodeStream(connection.getInputStream());
            connection.disconnect();
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return bitmap;
    }
}

? ? ? ?在這個類中我們實現(xiàn)了加載圖片、設(shè)置緩存,下載圖片三個基本功能。如此以來我們就實現(xiàn)了上文提出的需求。然而這樣的代碼僅僅適用于我們學習使用,在真實的正產(chǎn)環(huán)境當中由于需求會變的比較復雜,并且對可讀性,擴展性、后期維護都會有這較高的要求,如果這樣實現(xiàn)該功能,這個類會變得越來越大,代碼也越來越復雜,圖片加載系統(tǒng)也會越來越弱。這樣寫出的功能毫無設(shè)計可言,更不要說擴展性、靈活性了。所謂的單一職責原則,簡單的來說就是一個類負責一個功能。我們在此原則的基礎(chǔ)上對代碼進行拆分重構(gòu)。

ImageLoader類負責圖片加載功能,重構(gòu)后代碼如下:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;
import android.widget.ImageView;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import retrofit2.http.Url;

/**
 * 圖片加載類
 */
public class ImageLoader {
    ImageCache mImageCache=new ImageCache();
    //線程池,線程數(shù)量為CPU的數(shù)量
    ExecutorService mExecutorService= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    /**
     * 將下載的Bitmap對象顯示在Imageview上
     * @param url
     * @param imageView
     */
    public void displayBitmap(final String url, final ImageView imageView){
        imageView.setTag(url);
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
               Bitmap bitmap=downBitmap(url);
               if(bitmap==null)
               {
                   return;
               }
               if(imageView.getTag().equals(url))
               {
                   imageView.setImageBitmap(bitmap);
               }
                   mImageCache.put(url,bitmap);
            }
        });
    }

    /**
     * 通過URL下載圖片,并返回Bitmap
     * @param imageUrl
     * @return
     */
    public Bitmap downBitmap(String imageUrl)
    {
        Bitmap bitmap=null;
        try{
            URL url=new URL(imageUrl);
            final HttpURLConnection connection= (HttpURLConnection) url.openConnection();
            bitmap= BitmapFactory.decodeStream(connection.getInputStream());
            connection.disconnect();
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        return bitmap;
    }
}

ImageCache類負責圖片緩存功能代碼如下:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;
import android.widget.ImageView;
import java.net.URL;

/**
 * 圖片加載類
 */
public class ImageCache {
    LruCache<String, Bitmap> mImageCache;      
    public ImageCache(){
          initImageCache();
    }

    private void initImageCache()
    {
        //計算可以使用的最大內(nèi)存
        final int maxMemory= (int) (Runtime.getRuntime().maxMemory()/1024);
        //取可用內(nèi)存的1/4
        final int cachesize=maxMemory/4;
        mImageCache=new LruCache<String,Bitmap>(cachesize){
            @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);
      }

}

? ? ? ?我們將原來的代碼一拆為二。ImageLoader只負責圖片加載的邏輯,新創(chuàng)建一個類ImageCache只負責處理圖片緩存的邏輯,這樣ImageLoader的代碼量減少了,職責相對也變得更清晰了;當與緩存相關(guān)的邏輯需要修改時,圖片加載的邏輯不需要改變,而圖片加載邏輯需要改變時,也不會影響圖片緩存的邏輯。
? ? ? ?單一職責原則主要在于“單一”兩個字,如何劃分一個類,或者一個函數(shù),每個人根據(jù)自己的經(jīng)驗和業(yè)務(wù)邏輯都有自己不同的看法。但他也有一些基本規(guī)則的,如兩個完全不一樣的功能不應(yīng)該放在同一個類中。一個類中應(yīng)該是一組相關(guān)性較強的函數(shù)或者數(shù)據(jù)的封裝。我們要經(jīng)常審視自己的代碼,根據(jù)需要對類進行相應(yīng)的拆分。單一職責原則是優(yōu)化代碼需要邁出的第一步。

參考文獻:《Android源碼設(shè)計模式解析與實戰(zhàn)》 ----- 何紅輝 關(guān)愛民 著

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容