寫在前面#
新的主題確定了,這一次準(zhǔn)備總結(jié)Android設(shè)計(jì)模式,其實(shí)更準(zhǔn)確的說應(yīng)該叫做JAVA設(shè)計(jì)模式,這注定是一個(gè)浩大的工程,有你們陪著,我很快樂。
面向?qū)ο缶幊痰牧笤瓌t
- 單一職責(zé)原則
- 開閉原則
- 里氏替換原則
- 依賴倒置原則
- 接口隔離原則
- 迪米特原則
優(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)容之后你能夠有所收獲!感謝閱讀與喜歡!