面向对象的六大原则之 —— 里氏替换原则

时间:2021-01-28 17:24:09

学习了何红辉、关爱民写的《Android设计模式》,对于面向对象的六大原则有进一步的理解,特此根据自己的理解记录总结一下

什么是里氏替换原则

面向对象的语言有三大特性:封装、继承、多态,里氏替换原则就是依赖于继承、多态这两大特性,它的原则就是只要父类能出现的地方子类就能出现,而且不会报错,但是子类能出现的地方,父类不一定能出现,术语就是 —— 抽象。

在上一篇《面向对象的六大原则之 —— 开闭原则》中我们说了要让程序可扩展,其实开闭原则跟里氏替换原则是不离不弃的,它们两个基本都是同时出现。

在上一篇中,ImageLoader类通过依靠ImageCache实现图片缓存,而ImageCache只是一个接口,真正的实现还需要通过实现ImageCache接口进行具体的业务逻辑的实现,比如内存缓存MemoryCache、sd卡缓存DiskCache、双缓存DoubleCache,而用户需要自定义实现缓存方式,可以通过实现ImageCache接口进行具体的实现,这让ImageLoader充满了无限的可能性。

在以上的逻辑中,其实已经很好的体现了里氏替换原则,我们想一下如果ImageLoader类中的setImageCache(ImageCache imageCache),这个imageCache不能够被子类替换的话,那用户如何设置不同的缓存对象, 也完全不能自定义实现缓存方式,通过《面向对象的六大原则之 —— 开闭原则》中的if{}()else()来判断使用什么样的缓存方式吗?

  1. /** 
  2.      * 显示图片 
  3.      * @param url 图片的url 
  4.      * @param imageView 要显示的view 
  5.      */  
  6.     public void displayImage(final String url, final ImageView imageView) {  
  7.         Bitmap bitmap=null;  
  8.         if(isUseDoubleCache()){  
  9.             bitmap=doubleCache.get(url);  
  10.         }else if(isUseDiskCache()){  
  11.             bitmap=diskCache.get(url);  
  12.         }else{  
  13.             bitmap=imageCache.get(url);  
  14.         }  


这显然是不可行的,而里氏替换原则就是为这类问题提供指导原则,即建立抽象,通过抽象建立规范,我们的ImageCache用的是接口,其实是一样的,因为接口也是一种规范,我们通过实现了ImageCache接口达到不同的缓存策略,具体的实现在运行的时候进行设置:

  1. ImageLoader imageLoader=new ImageLoader();  
  2.         /** 
  3.          * 内存缓存方式 
  4.          */  
  5.         imageLoader.setImageCache(new MemoryCache());  
  6.         /** 
  7.          * SD卡缓存方式 
  8.          */  
  9.         imageLoader.setImageCache(new DiskCache());  
  10.         /** 
  11.          * 双缓存方式 
  12.          */  
  13.         imageLoader.setImageCache(new DoubleCache());  
  14.         /** 
  15.          * 自定义缓存方式 
  16.          */  
  17.         imageLoader.setImageCache(new ImageCache() {  
  18.             @Override  
  19.             public void put(String url, Bitmap bitmap) {  
  20.                 //用户自定义的缓存方式  
  21.             }  
  22.   
  23.             @Override  
  24.             public Bitmap get(String url) {  
  25.                 //从缓存中获取图片  
  26.                 return null;  
  27.             }  
  28.         });  

所以,利用开闭原则跟里氏替换原则来达到对扩展开发,对修改封闭的效果,这两个原则都强调了一个OOP的重要特性——抽象,所以在开发中,灵活运用抽象,是让代码优化的重要一步。

上一篇:《面向对象的六大原则之 —— 开闭原则》