開閉原則(Open Closed Principle)

開閉原則(Open Closed Principle)是Java世界里最基礎(chǔ)的設(shè)計原則,它指導(dǎo)我們?nèi)绾谓⒁粋€穩(wěn)定的、靈活的系統(tǒng)。

定義:一個軟件實體如類、模塊和函數(shù)應(yīng)該對擴展開放,對修改關(guān)閉。

簡單的說就是在修改需求的時候,應(yīng)該盡量通過擴展來實現(xiàn)變化,而不是通過修改已有代碼來實現(xiàn)變化。

舉一個簡單的例子:
  在圖片加載器ImageLoder中,我們需要將圖片緩存來加快軟件速度和節(jié)約用戶流量。我們一開始可能會考慮將從網(wǎng)絡(luò)上獲取到的圖片加載到內(nèi)存中去,并在第二次需要加載此圖片時直接從內(nèi)存中獲取。
于是,我們創(chuàng)建一個MemoryCache類。

注意:下面代碼只是模擬,省略了具體實現(xiàn)

//ImageLoder類 ,用于圖片加載

public class ImageLoder {

    //內(nèi)存緩存類
    MemoryCache mMemoryCache;

    //加載圖片
    public void displayImage(final String url, final ImageView imageView, Context context) {
        //使用緩存
        useCache(String url,mMemoryCache);
    }

    private void  useCache(String url,MemoryCache mMemoryCache){
        //從內(nèi)存中去獲取
        Bitmap bitmap= mMemoryCache.get( url);
        //如果內(nèi)存中沒有就通過網(wǎng)絡(luò)下載
        if(bitmap==null){
            //開啟線程,從網(wǎng)上下載圖片
            bitmap=downloadBitmap();
        }
        //將圖片存入內(nèi)存緩存
        mMemoryCache.put(url);
    }
    
}

//MemoryCache 內(nèi)存緩存類

public class MemoryCache {

   /*
   ** 省略具體實現(xiàn),具體實現(xiàn)使用LruCache類
   *  put()方法用來將圖片存入緩存。
   *  get()用于從緩存中取出圖片
   */

    public void put(String url, Bitmap bitmap) {
      
        /*
        ** 省略具體實現(xiàn)
        */
    }

    public Bitmap get(String url) {
      
        /*
        ** 省略具體實現(xiàn)
        */
    }

}

上面的MemoryCache 解決了每次從網(wǎng)上下載圖片的問題,但是Android 內(nèi)存有限。<font color=red face=“黑體”>單個應(yīng)用的最大內(nèi)存可以這樣獲?。篟untime.getRuntime().maxMemory()</font> 并且,具有易失性,即每次應(yīng)用重啟后,原來加載的圖片都會丟失,這樣又得從網(wǎng)絡(luò)下載。所以,我們考慮加入一個SD卡緩存類。這樣下載的圖片將緩存到本地。

//DiskCache sd卡緩存類


public class DiskCache  {

   /*
   ** 省略具體實現(xiàn)
   *  put()方法用來將圖片存入緩存。
   *  get()用于從緩存中取出圖片
   */

    public Bitmap get(String url) {

       /*
       ** 省略具體實現(xiàn)
       */
    }

    public void put(String url, Bitmap bitmap) {
       /*
       ** 省略具體實現(xiàn)
       */
    }

}

下面是修改后的ImageLoder類

public class ImageLoder {

    //內(nèi)存緩存類
    MemoryCache mMemoryCache;
    //sd卡緩存類
    DiskCache  mDiskCache;
    //用于判斷是否用MemoryCache,默認使用
    boolean isUseMemoryCache = true;

    //加載圖片
    public void displayImage(final String url, final ImageView imageView, Context context) {
        //根據(jù)useMemoryCahce來判斷Cache使用的類型
        if(useMemoryCahce){
        
            useMemoryCache(String url,mMemoryCache);
        }else{
        
            useDiskCache(String url,mMemoryCache);
        }
    }

    //使用MemoryCache
    private void  useMemoryCache(String url,MemoryCache mMemoryCache){
    
        Bitmap bitmap= mMemoryCache.get( url);
        if(bitmap==null){
            //開啟線程,從網(wǎng)上下載圖片
            bitmap=downloadBitmap();
        }
        //將圖片存入內(nèi)存緩存
        mMemoryCache.put(url);
    }
    //使用DiskCache
    private void  useDiskCache(String url,DiskCache  mDiskCache){
    
        Bitmap bitmap= mDiskCache.get( url);
        if(bitmap==null){
            //開啟線程,從網(wǎng)上下載圖片
            bitmap=downloadBitmap();
        }
        //將圖片存入內(nèi)存緩存
        mDiskCache.put(url);
    
    }
        
    //獲取isUseMemoryCache 
    private boolean useMemoryCahce(){
        return isUseMemoryCache ;
    }
    
    //設(shè)置isUseMemoryCache 
    private void SetUseMemoryCache(boolean isUseMemoryCache){
        this.isUseMemoryCache  =isUseMemoryCache ;
    }

}

在上面的代碼中,我們修改了 ImageLoader類,通過useMemoryCahce()方法來判斷使用哪一類型的cache.可以看到我們加入了一個if else語句來實現(xiàn)緩存的選擇功能。但是如果日后將cache的類型增加到十個甚至幾十個的時候,我們便需要再修改ImageLoder類,增加它的if else語句。在修改中可能會因各種因素使我們發(fā)生不必要的錯誤。顯然這不符合OCP原則。

有沒有什么方法可以讓我們擺脫if - else 語句(有人說用switch語句....這個這個)或者說讓我們不改動ImageLoader類來實現(xiàn)新功能呢?
答案肯定是有的。

下面我們使用接口來實現(xiàn)下上面的功能,給出一個uml類圖。

這里寫圖片描述

不會看UML類圖的請參考 5分鐘學會看UML類圖

在上圖中,創(chuàng)建了一個接口類,所有Cache類都實現(xiàn)該接口并重寫put 和get 方法。并增加了setImageCache(ImageCache mImageCache)方法用于用戶自定義cache類型,而一旦有新的cache類型產(chǎn)生的時候,只需要實現(xiàn)ImageCache接口,然后調(diào)用setImageCache方法即可實現(xiàn)并使用新cache類型。符合OCP的原則。

下面是重構(gòu)后的類。
//接口類

public interface ImageCache  {

    public Bitmap get(String url);

    public void put(String url, Bitmap bitmap);

}

//MemoryCache 內(nèi)存緩存類

public class MemoryCache implements ImageCache {

   /*
   ** 省略具體實現(xiàn),具體實現(xiàn)使用LruCache類
   *  put()方法用來將圖片存入緩存。
   *  get()用于從緩存中取出圖片
   */

    public void put(String url, Bitmap bitmap) {
      
        /*
        ** 省略具體實現(xiàn)
        */
    }

    public Bitmap get(String url) {
      
        /*
        ** 省略具體實現(xiàn)
        */
    }

}

//DiskCache sd卡緩存類


public class DiskCache implements ImageCache {

   /*
   ** 省略具體實現(xiàn)
   *  put()方法用來將圖片存入緩存。
   *  get()用于從緩存中取出圖片
   */

    public Bitmap get(String url) {

       /*
       ** 省略具體實現(xiàn)
       */
    }

    public void put(String url, Bitmap bitmap) {
       /*
       ** 省略具體實現(xiàn)
       */
    }

}

//ImageLoder類 ,用于圖片加載

public class ImageLoder {

    //默認使用內(nèi)存緩存類,也可以是其他Cache
     ImageCache cache = new MemoryCache();

    //用于自定義Cache類型
     public void setImageCache(ImageCache mImageCache) {

        this.mImageCache = mImageCache;
    }

    //加載圖片
    public void displayImage(final String url, final ImageView imageView, Context context) {
        //使用緩存
        useCache(String url,mImageCache);
    }

    private void  useCache(String url,ImageCachemImageCache){
    
        Bitmap bitmap= mImageCache.get(url);
        if(bitmap==null){
            //開啟線程,從網(wǎng)上下載圖片
            bitmap=downloadBitmap();
        }
        //將圖片存入內(nèi)存緩存
        mImageCache.put(url);
    }

}

開閉原則:當軟件需要修改時應(yīng)盡量通過擴展的方式來實現(xiàn),并不是說一定不能通過修改已有的代碼來實現(xiàn)。具體是否使用應(yīng)該由當前項目具體情況具體分析。

最后編輯于
?著作權(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)容