稳定而健壮的设计原则

本文详细介绍了面向对象设计的五大原则:开闭原则、单一职责原则、里氏替换原则、迪米特法则和接口隔离原则。这些原则旨在创建稳定、灵活和可维护的代码,提高软件设计质量。通过遵循这些原则,可以降低类之间的耦合度,提高系统的可扩展性和可维护性。同时,文章还探讨了依赖倒置原则,强调上层模块应依赖于抽象而非具体实现,以增强系统的灵活性。
摘要由CSDN通过智能技术生成

文章目录


Single Responsibility Principle:单一职责原则
Open Closed Principle:开闭原则
Liskov Substitution Principle:里氏替换原则
Law of Demeter:迪米特法则
Interface Segregation Principle:接口隔离原则
Dependence Inversion Principle:依赖倒置原则

把这六个原则的首字母联合起来就是 SOLID (稳定的),
代表的含义是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。



一、Open Closed Principle:开闭原则(OCP)

软件实体,如类、模块和函数应该遵守扩展开放和修改关闭的原则。

1、开: 对扩展进行开放

用抽象构建稳定的基本架构,用抽象的派生类来扩展实现易变的细节。


2、闭: 对修改进行关闭

这是因为对原有代码修改,往往可能引入新的错误;
这可能会使我们不得不重构。


相关案例:
设计原则 之 开闭原则



二、Single Responsibility Principle:单一职责原则(SRP)

一个类应该只有一个发生变化的原因,即: 一个类只负责一个职责。

这样的好处是:

1、类的复杂度低

每个类只负责单一的事情


2、代码容易维护,可读性高

代码职责划分清晰,不臃肿


SRP 也可以扩展到: 接口的单一职责 / 方法的单一职责。



三、Liskov Substitution Principle:里氏替换原则(LSP)

所有引用基类的地方,必须能透明地使用其子类的对象;
即: 所有基类在的地方,都可以换成子类,程序还可以正常运行。

1、为什么会有这个原则? 因为继承存在缺陷

这个原则是与面向对象语言的继承特性密切相关的,

继承优点:
代码可重用,减少开发类的工作量;
代码可扩展,子类不但拥有了父类的所有功能,还可以添加自己的功能。

继承缺陷:
继承是侵入性的:只要继承,就必须拥有父类的所有属性和方法;
降低代码灵活度:父类对子类存在约束;
增强耦合: 当需要修改父类代码时,必须考虑对子类的影响。


2、里氏替换原则,对继承进行规则约束,从而降低继承缺陷的影响

1) 子类必须重写父类的抽象方法,但不得重写父类的非抽象(已实现)方法;
若子类不对父类的抽象方法进行重写和实例化,那么这个接口或抽象类就毫无存在的意义了。

2)当子类重写父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格(返回值类型范围更小);

3)子类虽不能重写父类的已实现方法,但可以重载;子类重载父类方法需要有更宽松的形参;
当子类重载父类方法时,方法的前置条件(方法的形参)需要比父类方法的输入参数更宽松,
即输入允许访问更大,比如:子类:Map, 父类:HashMap。

4)子类中可以增加自己特有的方法,扩展功能。



四、Law of Demeter:迪米特法则(LOD)

只与你的直接朋友交谈,不要跟 “陌生人” 说话 :
如果两个软件实体无须直接通信,
那么就不应当发生直接的相互调用,应该通过第三方转发该调用;

1、LOD 优点

1)降低了类之间的耦合度,提高了模块的相对独立性。

2)由于亲合度降低,从而提高了类的可复用率和系统的扩展性。


2、LOD 缺点

过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低;
所以,在釆用迪米特法则时需要反复权衡,确保高内聚和低耦合的同时,保证系统的结构清晰。

从依赖者的角度来说,只依赖应该依赖的对象。
从被依赖者的角度说,只暴露应该暴露的方法。

客户找中介只需要在意符合自己条件的楼盘 ,而不必跟每个楼盘都发生联系。



五、Interface Segregation Principle:接口隔离原则

客户端不应该依赖它不需要的接口;
类间的依赖关系应该建立在最小的接口上。
即:要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

1、接口隔离原则 VS 单一职责原则

接口隔离原则和单一职责都是为了实现 “高内聚,低耦合“,体现了封装的思想,但两者也有点区别:

单一职责原则,主要注重对类的职责的约束,它针对的是程序中的实现和细节;
接口隔离原则,主要注重对接口依赖的隔离,它针对的是抽象和程序整体框架的构建。


2、衡量方法

1)根据接口隔离原则拆分接口时,首先必须满足单一职责原则;
2)接口拆分要有限度,比如一个接口只服务于一个子模块或业务逻辑。
3)为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。



六、Dependence Inversion Principle:依赖倒置原则(DIP)

上层模块不应该依赖底层模块,它们都应该依赖于抽象。
抽象不应该依赖于细节,细节应该依赖于抽象。

倒置,是指和一般 OO 设计的思考方式完全相反。

参考 实现一个比萨店的案例 来理解这个 “倒置” 。

举个例子
现在你需要实现一个比萨店,你第一件想到的事情是什么?
我想到的是一个比萨店,里面有很多具体的比萨,如:芝士比萨、素食比萨、海鲜比萨……
比萨店是上层模块,比萨是下层模块,
如果把比萨店和它依赖的对象画成一张图,看起来是这样:
正常依赖图

先从顶端开始,然后往下到具体类;
但是,实际上并不想让比萨店理会这些具体类,要不然比萨店将全都依赖这些具体类。

现在 “倒置” 你的想法……
别从上层模块比萨店开始思考,而是从下层模块比萨开始,然后想想看能抽象化些什么。
你可能会想到,芝士比萨、素食比萨、海鲜比萨都是比萨,
所以它们应该共享一个 Pizza 接口,即抽象化一个Pizza。

然后,回头重新思考如何设计比萨店:
依赖倒置后的图

图一的依赖箭头都是从上往下的,
图二的箭头出现了从下往上,
依赖关系确实 “倒置” 了!

另外,此例子也很好的解释了 “上层模块不应该依赖底层模块,它们都应该依赖于抽象。”
在最开始的设计中,高层模块 PizzaStroe 直接依赖低层模块(各种具体的Pizaa),
调整设计后, 高层模块和低层模块都依赖于抽象(Pizza) 。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值