此代码为 Android 设计模式学习
涉及到的设计原则有
1 单一职责原则 比如代码中的缓存和图片加载功能就是分开的
2 开闭原则
ocp通过对IImageCache接口的实现 以后的缓存修改都去实现这个接口
保证了在不改变当前代码的情况下添加新的功能
接口
public interface IImageCache {
Bitmap get(String url);
void put(String url,Bitmap bitmap);
}
实现类
public class ImageCacheSD implements IImageCache {
public static final String cacheDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp" + File.separator; //路径名
public ImageCacheSD() {
}
@Override
public Bitmap get(String url) {
return BitmapFactory.decodeFile(cacheDir + "/text0.jpg");
}
@Override
public void put(String url, Bitmap bitmap) {
Log.e("text123", "put: ");
FileOutputStream fileOutputStream = null;
try {
File file = new File(cacheDir);
if(!file.exists()) {
file.mkdirs();//新建目录
}
String newPath = "text0" + ".jpg"; //文件名
File files = new File(file,newPath);
fileOutputStream = new FileOutputStream(files);
boolean compress = bitmap.compress(Bitmap.CompressFormat.PNG, 80, fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("text123", "put: e = " + e.toString());
} finally {
CloseUtils.CloseStream(fileOutputStream);
}
}
}
public class ImageCache implements IImageCache {
LruCache<String, Bitmap> mImageLruCache;
public ImageCache() {
initImageLoader();
}
private void initImageLoader() {
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 4;
mImageLruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return super.sizeOf(key, value);
}
};
}
@Override
public void put(String url, Bitmap bitmap) {
mImageLruCache.put(url, bitmap);
}
@Override
public Bitmap get(String url) {
return mImageLruCache.get(url);
}
}
3 里氏替换原则 lsp
一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的 区别。即,子类型必须能够替换掉它们的父类型。
子类拥有父类所有非Private的行为和属性。
个人理解 就是子类继承父类(可以是具体的实体类 或者抽象类) 然后在使用的时候运用多态原理 调用的是父类的方法但是实现的是子类
4 依赖倒置
DIP 和LSP相比这个父类就是一个抽象接口 在使用的时候细节隐藏在这个接口的实现类里面 在使用的时候调 用的是接口的函数
共同点 都是用的是多态的原理隐藏具体的细节然子类自己实现自己的业务内容 在调用的时候只是调用上级类的函数从而得到结果
区别 LSP的关键在于继承(extends) 而SIP的关键在于实现(implements) LSP其实就是进一步封装的SIP 所以ISP相对于LSP更灵活一点
比如在实现图片加载的时候 可以用 ImageCacheDouble 也可以用 ImageCacheSD
他们都是实现了IImageCache接口 所以是依赖倒置
但是如果是 ImageCacheDouble extends IImageCache 什么的就是里氏替换了
说白了其实都是把细节隐藏还不影响扩展性
// ImageLoader loader = new ImageLoader(new ImageCacheDouble());
ImageLoader loader = new ImageLoader(new ImageCacheSD());
String str = "https://static.firefoxchina.cn/img/201904/8_5cc650135d39b0.jpg";
loader.displayImage(str,mMainIv);
5 接口隔离原则
类间的依赖关系应该建立在最小的接口上,接口隔离原则就是吧非常庞大的,
臃肿的接口拆分成更小的和更具体的接口 他的目标是系统解耦从而容易重构更改和重新部署
代码中的CloseUtils这个类就是这样的一个实现
其实我的理解就是用一个接口和一个实现类把一部分或者是一个功能独立出出来 使用代价就是会多些一些代码和接口
建议用在容易修改的地方或者重复多的函数中
/**
* 接口隔离原则
* fileOutputStream 实现了接口 Closeable
* 此接口用于负责流的关闭
*/
public class CloseUtils {
public static void CloseStream (Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用地点
@Override
public void put(String url, Bitmap bitmap) {
Log.e("text123", "put: ");
FileOutputStream fileOutputStream = null;
try {
File file = new File(cacheDir);
if(!file.exists()) {
file.mkdirs();//新建目录
}
String newPath = "text0" + ".jpg"; //文件名
File files = new File(file,newPath);
fileOutputStream = new FileOutputStream(files);
boolean compress = bitmap.compress(Bitmap.CompressFormat.PNG, 80, fileOutputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("text123", "put: e = " + e.toString());
} finally {
CloseUtils.CloseStream(fileOutputStream);
}
}
中的
CloseUtils.CloseStream(fileOutputStream);
6 迪米特原则
其实就是中介原则 适用于 多关系的业务逻辑中 比如有两种关系他们的直接的联系比较复杂的时候 可以在加入一个中间类来专门处理这样的逻辑