本文微信公众号「安卓小煜」首发

1. 布景

咱们应该都听过面向目标规划的 SOLID 准则,本文咱们就来唠一唠面向目标规划的六大准则,也就是 SOLID+迪米特准则。

2. SOLID 准则

2.1 单一责任准则

单一责任准则的英文名称是 Single Responsibility Principle,缩写是 SRP

SRP 的界说是,就一个类而言,应该仅有一个引起它改变的原因

简略来说,一个类中应该是一组相关性很高的函数、数据的封装

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

咱们要规划一个图片加载器。这个时分一个类里边假如咱们这样写:

class ImageLoader {
    void display(ImageView img) {
        // TODO
    }
    void setImageCache(String uri, Bitmap bitmap) {
        // TODO
    }
    Bitmap getImageCache(String uri) {
        // TODO
    }
}

咱们会发现这个图片加载器类既承当了图片加载的功用,也承当了图片缓存的功用。
当咱们图片加载的逻辑修改时,咱们需求来改动这个类的代码。
当咱们图片缓存的逻辑修改时,也需求来改动这个类的代码。
也就是说引起咱们图片加载器类改变的原因存在多个,不符合 SRP,因而咱们需求对其进行功用的解耦,把缓存给单独拎出来放到另一个类里边。

2.2 开闭准则

开闭准则的英文全称是 Open Close Principle,缩写是 OCP

OCP 的界说是,软件中的目标应该关于扩展是敞开的,可是,关于修改是封闭的

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

咱们规划的图片加载器。
图片缓存应该支撑多种缓存方式,而且要支撑用户自界说缓存。
因而需求供给一个接口给用户设置,经过依托注入的方式来确定详细的缓存战略。

interface ImageCache {
    void setImageCache(String uri, Bitmap bitmap);
    Bitmap getImageCache(String uri);
}
class ImageLoader {
    // 供给了接口让用户能够支撑缓存的自界说
    void setCacheStrategy(ImageCache cache) {
        // TODO
    }
}

2.3 里氏替换准则

里氏替换准则的英文全称是 Liskov Substitution Principle,缩写是 LSP不是lo s p

LSP 直截了当的界说是,一切引用基类的当地必须能透明地运用其子类的目标

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

仍是以咱们规划的图片加载器为例来进行阐明。
咱们能够看到,缓存的多种完成方式,依托的就是里氏替换准则,有了这个准则,用户假如要自界说缓存的完成方式,只需求写一个子类承继咱们的基类 ImageCache ,然后经过依托注入设置进去即可。
而这里依托注入能够成功的前提正是由于引用基类的当地能运用其子类的目标。所以说

里氏替换准则跟开闭准则是不离不弃的,经过里氏替换准则来达到对扩展敞开,对修改封闭的作用。

2.4 接口阻隔准则

接口阻隔准则的英文全称是 Interface Segregation Principle,缩写是 ISP

ISP 的界说是,客户端不应该依托它不需求的接口

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

咱们知道,在运用流进行文件的读写之后,咱们要及时进行封闭,否则就可能导致内存泄漏。

咱们运用流来读操作一般会写出下面的代码:

String filePath = "path/to/your/file.txt"; // 请替换为你的文件途径  
BufferedReader reader = null;  
try {  
    reader = new BufferedReader(new FileReader(filePath));  
    String line;  
    while ((line = reader.readLine()) != null) {  
        System.out.println(line);  
    }  
} catch (IOException e) {  
    e.printStackTrace();  
} finally {  
    if (reader != null) {  
        try {  
            reader.close();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}  

咱们会发现,流的封闭写的有点多层嵌套的样子,不行简练

if (reader != null) {
    try {  
        reader.close();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  
}  

因而咱们会考虑把流的封闭代码抽取出来,写到一个东西类里边,相似:

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

当然,有了上文的学习根底之后,咱们应该发现这个东西类写的有点问题,它依托的是详细而不是笼统,假如咱们换一个读文件的 API,咱们这个办法就不能运用了。
咱们跟踪了 BufferedReader,发现它的父类是 Reader,那是不是代表着咱们运用 Reader 来做参数就 OK 了呢?

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

假如你参数用 Reader,那么关于 Writer 或者 InputStream 又不通用了。
这里的一个做法其实就表现了 ISP

关于有封闭功用的类,它都能够完成 Closeable 接口,这个接口里边就一个 close 办法

因而,假如你自己写的一个类,有封闭的功用,也能够完成 Closeable 接口

Closeable 接口只供给了一个封闭办法,因而假如客户端有封闭需求,就能够依托它,而没有封闭需求的类,则不需求依托这个接口

所以关于封闭功用的封装,咱们能够写出如下代码:

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

ISP 使得咱们的这个公共办法能够给那些有封闭需求的类运用

2.5 依托倒置准则

依托倒置准则英文全称是 Dependence Inversion Principle,缩写是 DIP

DIPJava 语言中的表现是:模块间的依托经过笼统产生,完成类之间不产生直接的依托关系,其依托关系是经过接口或笼统类产生的。

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

上文中的图片加载器,缓存的多种完成方式,是经过依托注入来完成的。其依托关系是经过接口 ImageCache 来产生的。


以上就是面向目标编程的 SOLID 准则

单一责任 SRP
开闭准则 OCP
里氏置换 LSP
接口阻隔 ISP
依托倒置 DIP(依托回转)

3. 迪米特准则

迪米特准则的英文全称是 Law Of Demeter,缩写是 LOD

LOD 的界说是,一个目标应该对其他目标有最少的了解

解锁面向目标规划的六大准则:让你的代码更高雅、更可保护的诀窍

咱们应该都找过房子。
找房子咱们能够笼统出三个角色:租户、房子、中介。
关于租户来说,他只需求把想要的房子面积和接受价格等要求给到中介即可,而不需求自己去判别这个房子是不是符合他的要求,这些都是属于中介的责任。因而关于租户来说,他不需求对房子有了解。

4. 总结

以上就是面向目标规划的六大准则,也就是 SOLID+迪米特准则。
咱们在进行软件开发时,心里要牢记这些准则,可是又不硬套准则。

不管是准则仍是东西,终究的目的都只是为了让咱们的软件开发更有功率。


参考:
Android 源码规划模式解析与实战