里氏替换原则
简单来说就是,所有引用基类的地方,都能替换成对应的子类,也就是说父类能出现的地方,都能够用子类来替换
例如:
public class Window {
public void show(View child){
child.draw();
}
}
//抽象基类
public abstract class View {
public abstract void draw();
public void measure(int width ,int height){
//测量大小,统一处理
}
}
public class TextView extends View {
@Override
public void draw() {
//绘制 TextView
}
}
public class Button extends View {
@Override
public void draw() {
//绘制 button
}
}
如上,Window类依赖View,而View是所有视图的抽象基类,measure()
方法是子类共享的,draw()
方法是抽象的,子类自己实现各种各样的绘制功能. 这里任何继承自 View 的子类都可以设置给Window来显示出来
原来,里氏替换原则的核心是抽象和继承; 利用抽象和继承,可以把共享的内容统一处理,把差异的抽象,通过继承让子类来实现
依赖倒置原则
依赖倒置原则有以下几个特点:
(1). 调用者不应该直接依赖具体实现类,两者都应该依赖对应的抽象
(2).抽象中不应该直接依赖具体的实现类
(3).实现类应该依赖抽象
也就是说,两个实现类之间通过抽象类或者接口来关联,两个实现类不发生直接的依赖关系
例如:
public class ImageLoader {
//默认实现
private MemoryCache mImageCache = new MemoryCache();
public void setImageCache(MemoryCache cache){
mImageCache = cache;
}
public void displayImage( String url, ImageView imageView) {
Bitmap bitmap = mImageCache.get(url);
if(bitmap == null){
downloadImage(url,imageView);
}else {
imageView.setImageBitmap(bitmap);
}
}
}
这里ImageLoader
和MemoryCache
就直接发生了依赖关系,当想要改变缓存策略的时候,要添加一个SD缓存,或者双缓存,这个时候不但要改缓存类,同时也要修改ImageLoader这个类
遵循依赖倒置原则,两个类不应该直接依赖,修改为:
public class ImageLoader {
//通过引用抽象来依赖
private ImageCache mImageCache = new MemoryCache();
public void setImageCache(ImageCache cache){
mImageCache = cache;
}
public void displayImage( String url, ImageView imageView) {
Bitmap bitmap = mImageCache.get(url);
if(bitmap == null){
downloadImage(url,imageView);
}else {
imageView.setImageBitmap(bitmap);
}
}
}
只需要把原来的变量mImageCache
的类型MemoryCache
改为抽象ImageCache
通过引用抽象来发生依赖,setImageCache(ImageCache cache)
也是直接传入抽象,当需要改变缓存策略的时候,只需要修改对应的抽象实现就行,不会影响到ImageLoader
的内部逻辑代码.保证了缓存系统的可扩展性,拥有变化的能力,这就是依赖倒置原则
可以看出来,在面向对象语言里面,抽象是非常重要的一种手段