面向对象的SOLID原则白话篇

简介:

面向对象的SOLID原则

简介

缩写 全称 中文
S The Single Responsibility Principle 单一责任原则
O The Open Closed Principle 开放封闭原则
L Liskov Substitution Principle 里氏替换原则
I The Interface Segregation Principle 接口分离原则
D The Dependency Inversion Principle 依赖倒置原则

单一职责原则

一个类只应承担一种责任。换句话说,让一个类只做一件事。如果需要承担更多的工作,那么分解这个类。

举例

订单和账单上都有流水号、业务时间等字段。如果只用一个类表达,赋予其双重职责,后果:

  1. 特有属性和共有属性相互掺杂,难以理解;
  2. 修改一个场景可能会影响另一个场景。

正确的做法是拆成两个独立的类。

开放封闭原则

实体应该对扩展是开放的,对修改是封闭的。即,可扩展(extension),不可修改(modification)。

举例

一个商户接入了多个付款方式,支付宝和微信支付,如果将调用支付API的类写成:

public class PayHandler {

    public Result<T> pay(Param param) {
        if(param.getType() == "ALIPAY") {
            // 支付宝付款调用
            ...
        } else if(param.getType() == "WeChatPay") {
           // 微信支付付款调用
           ...
        }
    }
}

那么每次新加一种支付方式,或者修改原有的其中一种支付方式,都要修改PayHandler这个类,可能会影响现有代码。

比较好的做法是将不同的行为(支付方式)抽象,如下:

public class PayHandler {

    private Map<String, PayProcessor> processors;

    public Result<T> pay(Param param) {
        PayProcessor payProcessor = processors.get(param.getType());
        // 异常处理略
        return payProcessor.handle(param);
    }
}

interface PayProcessor {
    Result<T> handle(Param param);
}

public class AlipayProcessor implements PayProcessor {
    ...
}

public class WeChatPayProcessor implements PayProcessor {
    ...
}

这样,新增支付方式只需要新增类,如果使用的是spring等容器,在xml配置对应key-value关系即可;修改已有的支付方式只需要修改对应的类。最大化地避免了对已有实体的修改。

里式替换原则

一个对象在其出现的任何地方,都可以用子类实例做替换,并且不会导致程序的错误。换句话说,当子类可以在任意地方替换基类且软件功能不受影响时,这种继承关系的建模才是合理的。

举例

经典的例子: 正方形不是长方形的子类。原因是正方形多了一个属性“长 == 宽”。这时,对正方形类设置不同的长和宽,计算面积的结果是最后设置那项的平方,而不是长*宽,从而发生了与长方形不一致的行为。如果程序依赖了长方形的面积计算方式,并使用正方形替换了长方形,实际表现与预期不符。

扩展

不能用继承关系(is-a),但可以用委派关系(has-a)表达。上例中,可以使用正方形类包装一个长方形类。或者,将正方形和长方形作进一步抽象,使用共有的抽象类。

逸闻

“里氏”指的是芭芭拉·利斯科夫(Barbara Liskov,1939年-),是美国第一个计算机科学女博士,图灵奖、冯诺依曼奖得主,参与设计并实现了OOP语言CLU,而CLU语言对现代主流语言C++/Java/Python/Ruby/C#都有深远影响。其项目中提炼出来的数据抽象思想,已成为软件工程中最重要的精髓之一。(来源: 互动百科

接口分离原则

客户(client)不应被强迫依赖它不使用的方法。即,一个类实现的接口中,包含了它不需要的方法。将接口拆分成更小和更具体的接口,有助于解耦,从而更容易重构、更改。

举例

仍以商家接入移动支付API的场景举例,支付宝支持收费和退费;微信接口只支持收费。

interface PayChannel {
    void charge();
    void refund();
}

class AlipayChannel implements PayChannel {
    public void charge() {
        ...
    }
    
    public void refund() {
        ...
    }
}

class WeChatChannel implements payChannel {
    public void charge() {
        ...
    }
    
    public void refund() {
        // 没有任何代码
    }
}

第二种支付渠道,根本没有退款的功能,但是由于实现了PayChannel,又不得不将refund()实现成了空方法。那么,在调用中,这个方法是可以调用的,实际上什么都没有做!

改进

将PayChannel拆成各包含一个方法的两个接口PayableChannel和RefundableChannel。

依赖倒置原则

  1. 高层次的模块不应依赖低层次的模块,他们都应该依赖于抽象。
  2. 抽象不应依赖于具体实现,具体实现应依赖抽象。

实际上,依赖倒置是实现开闭原则的方法。

举例

开闭原则的场景仍然可以说明这个问题。以下换一种表现形式。

public class PayHandler {

    public Result<T> pay(Param param) {
        if(param.getType() == "ALIPAY") {
            AlipayProcessor processor = new AlipayProcessor();
            processor.hander(param);
            ...
        } else if(param.getType() == "WeChatPay") {
            WeChatPayProcessor processor = new WeChatPayProcessor();
            processor.hander(param);
           ...
        }
    }
}

public class AlipayProcessor { ... }

public class WeChatPayProcessor { ... }

这种实现方式,PayHandler的功能(高层次模块)依赖了两个支付Processor(低层次模块)的实现。

扩展:IOC和DI

控制反转(IOC)和依赖注入(DI)是Spring中最重要的核心概念之一,而两者实际上是一体两面的。

  • 依赖注入
    • 一个类依赖另一个类的功能,那么就通过注入,如构造器、setter方法等,将这个类的实例引入。
    • 侧重于实现。
  • 控制反转
    • 创建实例的控制权由一个实例的代码剥离到IOC容器控制,如xml配置中。
    • 侧重于原理。
    • 反转了什么:原先是由类本身去创建另一个类,控制反转后变成了被动等待这个类的注入。

后记

网络上很多文章中关于SOLID的介绍,语句都不通顺,徒增理解难度。如果对基本释义仍不能领会,可以参考 英文WIKI








本文转自五岳博客园博客,原文链接:http://www.cnblogs.com/wuyuegb2312/p/7011708.html,如需转载请自行联系原作者

目录
相关文章
|
4月前
|
设计模式 前端开发 关系型数据库
SOLID设计原则和我的一点个人感悟
SOLID设计原则和我的一点个人感悟
27 0
|
7月前
|
架构师 关系型数据库 程序员
空手撸SOLID架构设计原则,六大原则层层解析,你绝想不到
设计原则概述 通常来说,要想构建—个好的软件系统,应该从写整洁的代码开始做起。毕竟,如果建筑所使用的砖头质量不佳,那么架构所能起到的作用也会很有限。反之亦然,如果建筑的架构设计不佳,那么其所用的砖头质量再好也没有用。这就是SOLID设计原则所要解决的问题。
47 0
|
10月前
|
存储 关系型数据库
软件设计原则SOLID+组合聚合+迪米特原则(附代码讲解)
软件设计原则SOLID+组合聚合+迪米特原则(附代码讲解)
37 0
|
11月前
|
设计模式 搜索推荐 安全
【Java设计模式 经典设计原则】三 SOLID-LSP里式替换原则
【Java设计模式 经典设计原则】三 SOLID-LSP里式替换原则
99 0
|
11月前
|
设计模式 Java 关系型数据库
【Java设计模式 经典设计原则】五 SOLID-DIP依赖反转原则
【Java设计模式 经典设计原则】五 SOLID-DIP依赖反转原则
82 0
|
12月前
|
关系型数据库
面向对象的设计(OOD)原则了解一下
面向对象的设计(OOD)原则了解一下
135 0
|
设计模式 消息中间件 存储
软件设计 软件设计模式之SOLID原则
软件设计 软件设计模式之SOLID原则
70 0
|
安全
一分钟搞懂 SOLID 原则
一分钟搞懂 SOLID 原则
153 0
一分钟搞懂 SOLID 原则
面向对象基本原则(2)- 里式代换原则与依赖倒置原则
面向对象基本原则(1)- 单一职责原则与接口隔离原则 面向对象基本原则(2)- 里式代换原则与依赖倒置原则 面向对象基本原则(3)- 最少知道原则与开闭原则
|
设计模式 关系型数据库 程序员
设计模式之经典的 SOLID 原则
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
198 0