闲谈设计模式之单一原则
- 闲谈设计模式序论
- 单一原则(Single Responsibility Principle)
- 代码示例探讨SRP
- 常见动物呼吸案例
- 结合Android源码设计模式
- 总结
闲谈设计模式序论
闲谈设计模式是本人通过书籍、实际开发中总结所写,闲谈设计模式会以Java、Kotlin、Android源码进行分析讲解。
单一原则(Single Responsibility Principle)
单一原则:单一原则俗称SRP,其含义代表一个类应该仅有一个函数或者一个地方使其发生变化,近似的可以将一个类看成高度相关的一组函数或者一组组件,如果有多个地方可以引起其发生变化,那么这个类最终行为将变得不可预测,这对程序的把控风险大大提高。
- 优点:通过遵守SRP可以避免上帝类的创建,从而减少类的臃肿维护成本。
- 缺点:SRP的界限没有一个统一,基本都是由人而定,每个人的经验不一导致容易出现多余类的创建。
代码示例探讨SRP
常见动物呼吸案例
一个动物类有一个呼吸的方法代码如下:
public class Animal {
//有一个动物类,里面有一个呼吸的方法
public void breathe(@NotNull String animal) {
Log.i("SRP",(animal + "呼吸空气"));
}
}
上述代码仅仅适用于直接呼吸空气的动物,但是如果职责扩散了,呼吸的方法行为变得更细致细腻了呢很明显上述方法则不适用了。例如鱼这个种类那么代码又可以拓展成这样子来写了
public class Animal {
public void breathe(@NotNull String animal) {
if ("鱼".equals(animal)) {
Log.i("SRP",(animal + "呼吸水"));
} else {
Log.i("SRP",(animal + "呼吸空气"));
}
}
}
但是这样子的写法仅仅就对了吗?通过不断的添加添加判断会使得breathe这个方法变得更容于更沉重了。
还有一种做法就是直接继承Animal重写breathe方法,但是成千上万个动物需要示例的时候是否需要在一一创建呢显然不合理,避免类的冗余创建其实我们可以通过接口方式去实现代码如下:
public class Animal {
private String nameAnimal;
private Breathe breathe;
private interface Breathe{
void breathe();
}
public Animal(@NotNull String nameAnimal) {
this.nameAnimal = nameAnimal;
}
public void setBreathe(Breathe breathe) {
this.breathe = breathe;
}
public void breathe(){
if (breathe!=null) breathe.breathe();
}
}
通过使用Breathe接口使得类的创建避免了冗余,对于需要每个动物的呼吸行为则通过实现Breathe接口,区分得出breathe的行为。
结合Android源码设计模式
先来看一组UML图
public class ImageLoader {
//获取图片缓存
ImageCache imageCache = new ImageCache();
//线程池数量为cpu数量
ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//回调ui线程
Handler mUiHandler = new Handler(Looper.getMainLooper());
private void updateImageView(final ImageView imageView,final Bitmap bitmap){
mUiHandler.post(() -> {
imageView.setImageBitmap(bitmap);
});
}
public void displayImage(final String url,final ImageView imageView){
Bitmap bitmap = imageCache.get(url);
if (bitmap!=null){
updateImageView(imageView,bitmap);
}else {
mExecutorService.submit(() -> {
Bitmap downloadBitmap = downloadImage(url);
if (downloadBitmap==null)
return;
if (imageView.getTag().equals(url)){
updateImageView(imageView,bitmap);
}
imageCache.put(url,bitmap);
});
}
}
private Bitmap downloadImage(String url) {
Bitmap bitmap = null;
try{
URL url1 = new URL(url);
HttpURLConnection connection = (HttpURLConnection) url1.openConnection();
bitmap = BitmapFactory.decodeStream(connection.getInputStream());
connection.disconnect();
}catch (Exception e){
}
return bitmap;
}
}
public class ImageCache {
LruCache<String, Bitmap> mImageCache;
public ImageCache() {
initImageCache();
}
private void initImageCache() {
final int maxMermory = (int) (Runtime.getRuntime().maxMemory()/1024);
final int cacheSize = maxMermory/4;
mImageCache = new LruCache<String, Bitmap>(cacheSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight()/1024;
}
};
}
public void put(String url,Bitmap bitmap){
mImageCache.put(url, bitmap);
}
public Bitmap get(String url){
return mImageCache.get(url);
}
}
结合Android设计模式开篇源码,以及时序图可以得到遵循单一原则可以使得这样加载图片得一个工具类,维护起来十分简易,ImageCache只负责缓存图片,而ImageLoader则负责加载图片,充分体验单一原则的好处使得代码既不冗余并便于维护。
总结
合理的使用单一原则可以使得程序更好的维护,使得代码逻辑分层更加清晰可见,对某个单一功能仅仅维护其所在位置;滥用单一原则存在冗余类的创建,二逻辑分层可能会出现模糊甚至不可阅,三加重代码维护成本。