记得在最初学java时,老师给我们讲java面向对象时,说面向对象要遵循开闭原则,依赖倒闭原则…,那时觉得这是什么东西,听不懂啊,我们会用的着吗?
后来在刚开始工作中,领导说:XX你的代码不行啊,一点可维护性和拓展性都没有,这就是rubbish, 后来在开发中经常阅读别人的代码发现,他们写的代码结构特别清晰.再看看自己写的,根本没有可比性.
前段时间网上看到了Android源码设计模式这本书,觉得不错,就买了学习学习.下面记录下我学习的笔记.
-
单一职责原则 Single Responsibility Principle (SRP)
它表达出的用意就是"单一",也就是说一个类中应该是一组相关性很高的函数、数据的封装,也就是说一个类中的所有函数都是围绕一个点来写的,如果不是围绕这个点就重新建一个类来存放它。但是在实际开发中,单一职责原则的划分界限并不总是那么清晰,很多时候都是靠个人经验来界定的。 -
开闭原则 Open Close Principle (OCP)
开闭原则的定义:软件中的对象(类,模块,函数等)应该对于扩展是开发的,对于修改是关闭的.就是说在软件的升级维护中,我们应该尽量通过扩展的方式实现变化,而不是修改已有的代码. -
**里氏替换原则 Liskov Substitution Principle(LSP) **
其定义就是所有使用基类的地方可以使用子类来替换.它依赖于继承和多态这两大面向对象特性.核心原理就是抽象,抽象又依赖于继承.继承的优点
- 代码重用,减少创建类的成本,每个子类都拥有其父类的方法和属性
- 子类与父类基本相似,但又有区别
- 提高代码的可扩展性
继承的缺点:
- 继承是侵入性的,就是说只要继承就必须拥有父类的方法和属性
- 可能造成子类代码冗余,灵活性降低,因为其子类必须拥有父类的方法和属性
-
依赖倒置原则 Dependence Inversion Principle(DIP)
java语言中的表现:模块间的依赖通过抽象发生,实现类之间不直接发生的依赖关系,依赖关系是通过接口或者是抽象类发生的.
就是不同的类有相类似的功能,那么我们将功能抽取出来写成一个接口或者是抽象类,实现类实现接口或者继承抽象类实现各自功能,这就是依赖抽象不依赖与具体.
关键点:
- 高层模块不应依赖与低层模块,两者都应该依赖其抽象
- 抽象不应该依赖与细节
- 细节应依赖于抽象
-
接口隔离原则Interface Segregation Principle (ISP)
ISP的定义:客户端不应该依赖于他不需要的接口,也就是说,类间的依赖关系应该建议在最小的接口上,将非常庞大,臃肿的接口拆分成更小的和更具体的接口,这样客户端只需要知道他们感兴趣的方法.
ISP目的是系统的解耦,从而更容易重构、更改和重新部署。 -
迪米特原则 Law of Demeter (LOD)
LOD也称为最少知识原则(Least Knowledge Principle):一个对象应该对其他对象有最少的了解,类的内部如何实现与调用者没有关系,调用者只需知道他需要的方法,其他可以一概不管。这样使得系统具有更低的耦合与更好的可扩展性。 -
文章中的代码总结如下:
-
imageloader类
public class ImageLoader {
// 图片缓存对象 默认缓存为Memory
ICache cache = new ImageMemCache();
// 线程池
ExecutorService mThreadPools = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() / 2);
private static ImageLoader instance;
Message msg = Message.obtain();
ImageView iv;
private Bitmap bm;
/**
* 使用handler,looper实现不同线程的通信
*/
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
iv.setImageBitmap(bm);
}
};
/**
* 使用单例获取imageloader对象
*
* @return
*/
public static ImageLoader getInstance() {
if (null == instance) {
synchronized (ImageLoader.class) {
if (null == instance) {
instance = new ImageLoader();
}
}
}
return instance;
}
/**
* 加载图片,将图片显示到imageview上,先从缓存中获取图片,如果获取不到,则从网络获取
*
* @param url
* @param imageView
*/
public void displayImage(final String url, final ImageView imageView) {
Bitmap bitmap = cache.get(md5(url));
if (null != bitmap) {
imageView.setImageBitmap(bitmap);
return;
}
imageView.setTag(url);
mThreadPools.submit(new Runnable() {
@Override
public void run() {
Bitmap bitmap = downloadImage(url);
if (bitmap == null) {
return;
}
if (imageView.getTag().equals(url)) {
iv = imageView;
bm = bitmap;
handler.sendEmptyMessage(0);
}
cache.put(md5(url), bitmap);
}
});
}
/**
* 通过HttpURLConnection获取网络图片
*
* @param imageUrl
* @return
*/
private Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
try {
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 设置图片缓存模式
*
* @param cache
*/
public void setImageCache(ICache cache) {
this.cache = cache;
}
/**
* 将图片网站转换为md5字符串
* @param str
* @return
*/
private String md5(String str) {
byte[] digest = null;
try {
MessageDigest messageDigest = MessageDigest.getInstance("md5");
digest = messageDigest.digest(str.getBytes());
return bytes2hex02(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
/**
* @param bytes
* @return
*/
public String bytes2hex02(byte[] bytes) {
StringBuilder sb = new StringBuilder();
String tmp = null;
for (byte b : bytes) {
tmp = Integer.toHexString(0xFF & b);
if (tmp.length() == 1){
tmp = "0" + tmp;
}
sb.append(tmp);
}
return sb.toString();
}
}
- ICache 接口
public interface ICache {
public Bitmap get(String url);
public void put(String url, Bitmap bitmap);
}
- ImageCache
public class ImageCache implements ICache {
ImageMemCache memCache = new ImageMemCache();
ImageDiskCache diskCache = new ImageDiskCache();
@Override
public Bitmap get(String url) {
Bitmap bitmap = memCache.get(url);
if (null == bitmap) {
bitmap = diskCache.get(url);
}
return bitmap;
}
@Override
public void put(String url, Bitmap bitmap) {
memCache.put(url, bitmap);
diskCache.put(url, bitmap);
}
}
- ImageMemCache
public class ImageMemCache implements ICache {
// 图片内存缓存
LruCache<String, Bitmap> mImageCache;
public ImageMemCache() {
initImageCache();
}
public void initImageCache() {
// 获取最大内存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 4;
mImageCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
};
}
@Override
public void put(String url, Bitmap bitmap) {
mImageCache.put(url, bitmap);
}
@Override
public Bitmap get(String url) {
return mImageCache.get(url);
}
}
- ImageDiskCache
public class ImageDiskCache implements ICache {
@Override
public Bitmap get(String url) {
return BitmapFactory.decodeFile(getMDir() + url);
}
@Override
public void put(String url, Bitmap bitmap) {
FileOutputStream outputStream = null;
// 检测目录是否存在
File file = new File(getMDir());
if (!file.exists()) {
file.mkdir();
}
File path = new File(getMDir() + url);
Log.e("file", path.getAbsolutePath());
try {
// 将图片压缩到sdcard中
outputStream = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
CloseUtils.close(outputStream);
}
}
/**
* 获取sdcard中缓存图片的目录
*
* @return
*/
private String getMDir() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return Environment.getExternalStorageDirectory() + "/DESIGN_TEST/";
} else {
throw new RuntimeException("sdcard is unmounted");
}
}
}
- CloseUtils
public class CloseUtils {
public static void close(Closeable closeable) {
if (null != closeable) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
可能有些地方写的不好,望大家指正啊!!!