美文网首页
面向对象六大原则

面向对象六大原则

作者: Dane_404 | 来源:发表于2019-03-20 08:36 被阅读0次

1、面向对象的六大原则

1、单一职责原则

  • 简单的说,一个类应该是一组相关性很高的函数和数据的封装,也就是一个类一个功能。
  • 比如:一个图片加载器ImageLoader,可能大多代码都是封装成一个类,也就是图片的加载逻辑和图片的缓存逻辑在一起,而运用单一职责原则,是把图片加载逻辑和图片缓存逻辑分开成两个类,一个ImageLoader,一个ImageCache,这样ImageCache只负责图片的缓存,将ImageLoader的代码量减少了,职责清晰了,耦合度也降低,修改时各自的逻辑时也不会相互影响。

2、开闭原则

  • 这里深有体会,所谓的开闭原则,就是对扩展开发,对修改关闭,但现实没这么绝对,应该是应该尽量通过扩展方式来实现变化,而不是通过修改原有代码来实现。

  • 还是ImageLoader为例:
    原来的ImageCache只有内存缓存,需要多一种本地缓存,好吧,运用单一职责原则,就分成三个类ImageLoader、MemoryCache、DiskCache,然后ImageLoader代码为:

    public class ImageLoader {
      
          MemoryCache mMemoryCache = new MemoryCache();
          DiskCache mDiskCache = new DiskCache();
          boolean isUseDiskCache = false;
      
          ExecutorService mExecutorService
                  = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
      
          public void display(String url, ImageView imageView){
              Bitmap bitmap = isUseDiskCache ? mDiskCache.get(url) : mMemoryCache.get(url);
              if (bitmap != null){
                  imageView.setImageBitmap(bitmap);
                  return;
              }
              //没有缓存就网络加载
          }
      
          public void setUseDiskCache(boolean useDiskCache){
              isUseDiskCache = useDiskCache;
          }
      }
    

    上面的代码存在的问题,多了一个本地缓存,需要去修改ImageLoader的逻辑,需要增加set方法,当然这里看不出什么,而实际项目中,但功能代码多复杂,很可能修改后出现BUG,那么运用开闭原则效果如下:
    首先定义接口ImageCache,让MemoryCache和DiskCache实现:

    public interface ImageCache {
    
      Bitmap get(String url);
    
      void put(String url, Bitmap bitmap);
    }
    //MemoryCache 
    public class MemoryCache implements ImageCache {
      
          private LruCache<String,Bitmap> mLruCache;
      
          public MemoryCache() {
              //初始化mLruCache
          }
      
          @Override
          public Bitmap get(String url) {
              return mLruCache.get(url);
          }
      
          @Override
          public void put(String url, Bitmap bitmap) {
              mLruCache.put(url,bitmap);
          }
      }
     //DiskCache 
    public class DiskCache implements ImageCache {
        @Override
        public Bitmap get(String url) {
            return null;   //本地获取
        }
    
        @Override
        public void put(String url, Bitmap bitmap) {
                //本地存
        }
    }
    

    接下来看ImageLoader:

    public class ImageLoader {
    
          private ImageCache mImageCache = new MemoryCache();//默认内存缓存
    
          ExecutorService mExecutorService
                  = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    
          public void display(String url, ImageView imageView){
              Bitmap bitmap = mImageCache.get(url);
              if (bitmap != null){
                  imageView.setImageBitmap(bitmap);
                  return;
              }
              //没有缓存就网络加载
          }
    
         public void setImageCache(ImageCache imageCache){
             mImageCache = imageCache;
         }
      }
    

    看到这里有很深的体会,使用就这样:

     ImageLoader imageLoader = new ImageLoader();
     imageLoader.setImageCache(new DiskCache()); 
    

    使用者也可以继承ImageCache去扩展,回头想下:对扩展开放,对修改关闭。

3、里氏替换原则

  • 定义:所有引用基类的地方必须能够正确的使用其子类对象,其实就是继承和多态。
  • 上面的ImageCahe就是里氏替换原则,在ImageLoader中使用了ImageCahe,它的子类都有put和set的功能,它们都可以替代 ImageCahe工作。

4、依赖倒置原则

  • 概念的东西很抽象,一句话概况就是面向接口编程,目的就是解耦。
  • 没错,还是上面的ImageLoader,ImageLoader依赖于ImageCache而不是依赖于MemoryCahe或者DiskCache,这样加载模块和缓存模块不直接发生关系,通过接口间接产生关系。
  • 这样在来看依赖倒置原则的特点就能理解:高层模块不应该依赖底层模块,两者应该依赖抽象,高层模块就是调研端,也就是ImageLoader,底层模块就是实现类,也就是MemoryCache或者DiskCache,抽象就是接口ImageCache。

5、接口隔离原则

  • 说白了,就是让客户端依赖的接口尽可能的小,好吧,还是很抽象,直接上个例子:
    上面的DiskCache必然要用到OutputSteam, 它实现了一个叫Closeable的接口:

       try {
              outputStream.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
    

    很显然,看到try...catch很不爽,每次都要写,果断封装下:

     public void close(Closeable closeable){
      if (closeable != null){
          try {
              closeable.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
    }
    

    这样提高了重用性,并且建立在最小依赖原则的基础上,它只需要知道这个对象是可关闭,其他不关心。通过Closeable接口将可关闭的对象抽象起来,这样客户端依赖于Closeable就可以对客户端隐藏其他接口信息,客户端只需要知道这个对象可关闭即可。

6、迪米特原则

  • 通俗的说,一个类应该对自己需要耦合或调用的类知道得最少,类的内部如何实现与调用者或者依赖这没关系,调用者或依赖者只需要知道它需要的方法即可。

  • 以中介的例子为例,找中介找房:
    如果是这样:

    public class Room {
         
        public String area;
        public String price;
    
        public Room(String area, String price) {
            this.area = area;
            this.price = price;
        }
    }
    //中介
    public class Mediator {
    
         List<Room> mRooms = new ArrayList<>();
    
         public Mediator(){
             for(int i = 0;i < 5; i++){
                 mRooms.add(new Room(14+i,(14+i)*150));
             }
         }
    
         public List<Room> getRooms(){
             return mRooms;
         }
     }
    //租客
    public class Tenant {
      
          private float area = 60;
          private float price = 2000;
      
          public void rentRoom(Mediator mediator){
              for (Room room : mediator.getRooms()) {
                  if (room.area >= area && room.price <= price){
                      System.out.println("找到了");
                      return;
                  }
              }
          }
      }
    

    看到一个问题,租客想找房,他不应该和Room打交道,也就是Tenant 类不应该出现Room类,分清关系,Room应该和Mediator打交道,Tenant只和Mediator打交道,那么这样:

    public class Mediator {
    
        List<Room> mRooms = new ArrayList<>();
    
        public Mediator(){
            for(int i = 0;i < 5; i++){
                mRooms.add(new Room(14+i,(14+i)*150));
            }
        }
    
        public Room rentOut(float area,float price){
            for (Room room : mRooms) {
                if (room.area >= area && room.price <= price){
                    return room;
                }
            }
            return null;
        }
    } 
    
    public class Tenant {
    
          private float area = 60;
          private float price = 2000;
    
          public void rentRoom(Mediator mediator){
             mediator.rentOut(area,price);
          }
      }

相关文章

  • 面向对象六大原则

    面向对象六大设计原则:

  • Android 设计模式之常见设计模式总结

    今天我们来总结下我们所学习的设计模式 面向对象的六大原则 Android 设计模式之面向对象的六大原则 面向对象的...

  • 面向对象六大原则

    面向对象六大原则 单一原则 [Single Responsibility Principle 简称 SRP] ...

  • 设计模式

    设计原则: 面向对象需要遵循的六大原则: 单一职责原则(SingleResponsibilityPrinciple...

  • 面向对象六大原则

    设计模式的六大原则:(面向对象的六大原则) 一、单一职责原则:Single Responsibility Prin...

  • 设计模式六大原则

    设计模式六大原则 一、面向对象设计六大原则 面向对象的关键在于封装,封装好了才能很好的复用,达到单一职责和开放扩展...

  • 面向对象的六大原则

    面向对象六大原则 单一职责原则--SRP(Single Responsibility Principles)每个类...

  • 纯干货!23种设计模式大总汇

    一、面向对象的六大原则 单一职责原则——Single Responsiblity Principle 迪米特原则—...

  • 面向对象的六大原则

    设计模式基础 面向对象的六大原则 单一职责原则(Single Responsibility Principle, ...

  • JAVA设计模式

    面向对象设计的六大设计原则 1、单一职责原则(Single Responsibility Principle, S...

网友评论

      本文标题:面向对象六大原则

      本文链接:https://www.haomeiwen.com/subject/dfzomqtx.html