软件设计 软件设计模式之SOLID原则
软件设计模式之SOLID原则
By:授客 QQ:1033553122
#单一职责原则(SRP)
定义:任何一个软件模块都只对某一类行为者负责
说明:这里“软件模块”,在大部分情况下,可以简单定义为一个源代码文件、一个类、一组紧密相关的函数和数据结构、
#开闭原则(OCP)
定义:软件实体应当对扩展开放,对修改关闭
说明:这里的“软件实体”包含模块,类,接口,方法等
开闭原意在告诉我们,当应用的需求改变时,在不修改软件实体原有的源代码或者二进制代码的前提下,可以通过新增代码来满足新的需求,也就是说一个设计良好的计算机系统应该在不需要修改的前提下就可以轻易被扩展,这是架构的根本目的,如果对原始需求的小小延伸就需要对原有的软件系统进行大幅修改,那么这个系统的架构设计显然是失败的。
在Java、C++这类语言中,可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。 因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
而在python中一切都是对象,可以指向任何类型,所以,不用定义接口变可实现类似接口。
#里氏替换原则(LSP)
第一种定义:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2 时,程序P的行为没有发生变化,那么类型 S 是类型 T 的子类型。
第二种定义:所有引用基类的地方必须能透明地使用其子类的对象。
第一种定义是最正宗的定义,而第二种定义则是最清晰明确的,通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会 产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应
里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,即基类随便怎么改动子类都不受此影响,那么基类才能真正被复用
因为继承带来的侵入性,增加了耦合性,也降低了代码灵活性,父类修改代码,子类也会受到影响,要让程序遵守里氏替换原则,实现继承时必须遵守以下几点:
1)子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
2)当子类覆盖或实现父类的方法时,方法的的形参要比父类方法的输入参数更宽松。
3)当子类的方法实现父类的抽象方法时,方法的返回值要比父类更严格。
4)遵守以上几点的情况下,无法满足需求时,可以考虑在子类中增加自己特有的方法。
#接口隔离原则(ISP)
定义:
1、客户端不应该依赖它不需用的接口
2、类间的依赖关系应该建立在最小的接口上。
简单理解就是,不要在一个接口里面放很多的方法,这样会显得这个类很臃肿,java接口类为例,继承接口的非抽象子类,都要实现接口类的拥有的所有方法,所以,当这些子类仅需要要接口类中的部分方法时还是需要去实现对其没有意义的接口方法,所以,接口应该尽量细化,一个接口对应一个功能模块,同时接口里面的方法应该尽可能的少,使接口更加灵活轻便。但是需要注意的是:拆分要适度度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
接口隔离原则和单一职责原则虽然很类似,但是两个原则还是存在着明显的区别。单一职责原则是在业务逻辑上的划分,注重的是职责。接口隔离原则是基于接口设计考虑。
#依赖反转原则(DIP)
依赖反转原则被称作依赖倒置原则,
定义:
1)高层策略性的代码不应该依赖实现底层细节的代码
2)抽象不应该依赖于细节,细节应该依赖于抽象
说明:
1、什么是“高层”,什么是“细节”?
对一个系统来说,业务逻辑是高层,其他是细节。业务逻辑是仅仅包括用例、业务实体部分,不包括任何框架、存储(数据库)、其他系统等部分,是纯粹的。其他细节,包括框架、数据库、消息队列,都是细节。业务逻辑应该不依赖任何细节。细节的实现可以任意替换而不影响业务逻辑。
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定得多,其中心思想是面向接口编程
该原则告诉我们,如果想要设计一个灵活的系统,在源代码层次的依赖关系中就应该多引用稳定的抽象类型,而非具体实现,特别注意不要在具体实现类上创建衍生类,不要覆盖包含具体实现的函数。Java中,抽象多指的是接口或抽象类,用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
显而易见,把这条设计原则当成金科玉律来加以严格执行是不现实的,因为在实际构造系统的过程中,不可避免的依赖一些具体实现,比如java的String类就是这样一个具体实现,我们将其强迫的转化为抽象类是不现实的。类似String类这种本身是非常稳定的类、模块,可以不用考虑,需要多关注的是经常会变动的具体实现模块。
在Python中,可以不通过抽象类的方式很轻松的实现依赖反转
例子:音乐玩具播放器模拟程序,要求可以播放各种动物的声音。
最开始,这个玩具的要求比较简单,一开始只要求播放一种动物声音,鸟叫声
Bird.java
publicclass Bird{
publicvoid call(){
System.out.println("bird call");
}
}
ToyPlayer.java
publicclass ToyPlayer{
publicvoid play(Bird bird){ #这里的入参,引用的是具体的实现类
bird.call();
}
}
Entry.java
publicclass Entry {
publicstaticvoid main(String[] args){
ToyPlayer player = new ToyPlayer();
Bird bird = new Bird();
player.play(bird);
}
}
如上,以上代码是不符合依赖反转原则的,播放器类,依赖具体的动物类(实现类),当需求变化时可能无法满足需求。比如,需要给玩具增加其它动物声,比如狗叫,这个时候就需要更改程序了。
改进版
Animal.java
interface Animal{
publicvoid call();
}
Bird.java
publicclass Bird implements Animal{
publicvoid call(){
System.out.println("bird call");
}
}
Dog.java
publicclass Dog implements Animal{
publicvoid call(){
System.out.println("dog call");
}
}
ToyPlayer.java
publicclass ToyPlayer{
publicvoid play(Animal animal){ #注意,这里替换了参数类型--替换具体类类型 Bird 为抽象类类型 Animal
animal.call();
}
}
Entry.java
publicclass Entry {
publicstaticvoid main(String[] args){
ToyPlayer player = new ToyPlayer();
Bird bird = new Bird();
player.play(bird);
Dog dog = new Dog();
player.play(dog);
}
}
软件设计 软件设计模式之SOLID原则的更多相关文章
- 实践GoF的23种设计模式:SOLID原则(上)
摘要:本文以我们日常开发中经常碰到的一些技术/问题/场景作为切入点,示范如何运用设计模式来完成相关的实现. 本文分享自华为云社区<实践GoF的23种设计模式:SOLID原则(上)>,作者: ...
- 设计模式之SOLID原则
介绍 设计模式中的SOLID原则,分别是单一原则.开闭原则.里氏替换原则.接口隔离原则.依赖倒置原则.前辈们总结出来的,遵循五大原则可以使程序解决紧耦合,更加健壮. SRP 单一责任原则 OCP 开放 ...
- [JavaEE]设计模式之SOLID原则
1. S The Single Responsibility Principle 单一责任原则 当需要修改某个类的时候原因有且只有一个(THERE SHOULD NEVER BE MORE THA ...
- 设计模式、SOLID原则:组件与联系
组件原则 - SRP The Single Responsibility Principle 单一责任原则 当需要修改某个类的时候原因有且只有一个.换句话说就是让一个类只做一种类型的责任,当这个类需要 ...
- 一篇文章带你了解设计模式原理——UML图和软件设计原则
一篇文章带你了解设计模式原理--UML图和软件设计原则 我们在学习过程中可能并不会关心设计模式,但一旦牵扯到项目和面试,设计模式就成了我们的短板 这篇文章并不会讲到二十三种设计模式,但是会讲解设计模式 ...
- 【译】浅谈SOLID原则
SOLID原则是一种编码的标准,为了避免不良设计,所有的软件开发人员都应该清楚这些原则.SOLID原则是由Robert C Martin推广并被广泛引用于面向对象编程中.正确使用这些规范将提升你的代码 ...
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- C#软件设计——小话设计模式原则之:单一职责原则SRP
前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛.博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文.博主的想法是,既然要完善知识体系 ...
- C#软件设计——小话设计模式原则之:开闭原则OCP
前言:这篇继续来看看开闭原则.废话少说,直接入正题. 软件设计原则系列文章索引 C#软件设计——小话设计模式原则之:依赖倒置原则DIP C#软件设计——小话设计模式原则之:单一职责原则SRP C#软件 ...
随机推荐
- 线程同步 进程同步 EventWaitHandle
这个名字LLLLL取相同就能让同一台电脑上两个进程同步 主动控制程序 class Program { static EventWaitHandle eHandle = new EventWaitHan ...
- ISCC 2024 练武题 misc趣题记录
Number_is_the_key 题目 The answers to the questions are hidden in the numbers. 文件是空白的xlsx文件 我的解答: 乱点发现 ...
- 002. git 分支管理
git分支 git分支,从本质上来讲仅仅是指向提交对象的可变指针,在这一点上与svn是有着本质区别,svn的分支实际就是个目录而已. git默认分支名字是 master,在多次提交操作后,你其实已经有 ...
- FlexBox 行间距
问题背景 在Flex布局方式下, 父容器约定是换行的方式, 不足以容纳一行子元素的时候, 会单独进行折行, 那么折行的行间距如何处理呢? 解决办法 通过在子Item上面设置margin-top可以模拟 ...
- 第一次线上 OOM 事故,竟和 where 1 = 1 有关
这篇文章,聊聊一个大家经常使用的编程模式 :Mybatis +「where 1 = 1 」. 笔者人生第一次重大的线上事故 ,就是和使用了类似的编程模式 相关,所以印象极其深刻. 这几天在调试一段业务 ...
- 高可用集群MHA方案
爱奇艺在用的数据库高可用方案 MHA 是目前比较成熟及流行的 MySQL 高可用解决方案,很多互联网公司正是直接使用或者基于 MHA 的架构进行改造实现 MySQL 的高可用. MHA 能在 30 秒 ...
- CountDownLatch demo演示数据分片多线程处理
# CountDownLatch demo演示数据分片多线程处理 package com.example.core.mydemo; import org.springframework.schedul ...
- svn服务端安装和使用
首先去官网下载安装包 点我下载 下载完了以后选择安装路径然后一直next就可以了 安装完了以后在开始菜单里面找到svn 打开 如何使用? 这里是创建代码管理的存储库 点击 repositories ...
- 洛谷 P1226 快速幂
题目链接:快速幂 思路 简单快速幂模板.a ^ 17 = (a ^ 2) ^ 8 * a,此时pow()中的y就可以视为17 -> 8(y >>= 1),pow()中的x就是底数a ...
- CLR via C# 笔记 -- 线程基础(26)
1. Microsoft 设计这个OS内核时,决定在一个进程中运行应用程序的每个实例.进程实际是应用程序的实例要使用的资源的集合.每个进程都被赋予了一个虚拟地址空间,确保在一个进程中使用的代码和数据无 ...