首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >我用过的设计模式(1)-- 本门心法

我用过的设计模式(1)-- 本门心法

原创
作者头像
看、未来
修改于 2021-02-25 02:15:19
修改于 2021-02-25 02:15:19
3470
举报
在这里插入图片描述
在这里插入图片描述

单一职责原则

什么是“单一职责原则”?

如果要理解为:一个类只有一个职责,当然也是可以的,简单化嘛。

单一职责的原话解释是这样的:There should never be more than one reason for a class to change.

什么意思?那里,应该,没有,多于,一个,原因,使得,类,去,改变。

啊,咱这蹩脚英语,勉强能翻译啊。

不过,能看懂是一回事,具体实现就是另一个故事了。。。

饱受争议的原则

为什么饱受争议呢?看着多单纯一原则啊。

这样,我们来看一个打电话的过程:

class 电话{

public:

代码语言:txt
AI代码解释
复制
void 拨出电话(string 电话号码);
代码语言:txt
AI代码解释
复制
void 瞎比比(Object *哔哔类对象);	//总不能传个string吧,说一句就没啦?
代码语言:txt
AI代码解释
复制
void 挂电话();

};

这个有没有问题?是有那么小问题的嘞。

你说我哪天,拨号的方法要改一下,我变成拨不通就一直拨,那这个类变一下。

然后我通信的方法再改一下,我现在不允许两个人同时说话,一个说完另一个再说,那这个类再变一下。

这个类,有两个职责:协议管理和数据传送。

那怎么搞?把那俩接口独立出来呗,然后将两个职责融合在一个类中。

在这里插入图片描述
在这里插入图片描述

现在变成了一个类融合了两个接口,确实那个实现类还是有两个原因引起变化,但是别忘了,我们是面向接口编程(后面会提到,依赖倒置原则)。我们对外公布的是接口,又不是实现类。

如果你非要对这个栗子实现单一原则,也可以,你要有那个权力或精力(因为我估计没人愿意陪你这样玩)。

“单一职责原则”的优势

  • 类的复杂性降低,实现什么职责都有明确的定义。 ==这是最首要的,如果不能降低复杂度,那就别分开==
  • 可读性提高
  • 可维护性提高
  • 变更引起的风险降低

怎么用?自己看着办

==对于接口,我们在实现的时候一定要做到单一==,但是对于实现类就需要多方面考虑了。

生搬硬套的话会有什么不良反应,去试试就知道了。

单一职责很难在项目中得到体现,就拿上面那栗子来说,能把接口分开就谢天谢地吧。

当然,单一职责也可以用于类方法,说来惭愧,我曾经用一个类方法实现五个功能(通过巧妙设置参数)。。。。

现在想想,真是好笑啊。


里氏替换原则

什么是“里氏替换原则”?

这个原则,说简单也简单,说拗口也拗口。

是这样说的:Function that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基类的地方,必须能透明的使用其子类对象。

什么意思呢?就是子类必须实现父类的所有方法。有父类出现的地方,子类就可以出现。

关于里氏替换原则

关于里氏替换原则,我并不想讲太多,无非就是父类弄成纯虚基类,然后客端调用的时候以子类来new出父类声明的对象:父类 * 对象 = new 某子类();

这种格式后面会常见,见到的时候自然就明白了。


依赖倒置原则

什么是“依赖倒置原则”

这是我最喜欢的一个原则,也是受益最大的。

它的定义是:High level modules should not depend upon low level modules. Both should depend upon abstractions. Absteactions should not depend upon details.Details should depend upon abstractions.

  • 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
  • 抽象不应该依赖于细节。
  • 细节应该依赖于抽象。

关于依赖倒置原则的小故事

故事是别人的,不过放在这里也是很应景啦。

故事是这样的:

有个适龄小伙子,他还单着。有一天,他喜欢的那个姑娘突然给他打电话,说她的电脑坏了,一用就蓝屏警告。姑娘讲着讲着就要哭出来了,小伙子那个急啊,他心疼啊。所幸,小伙子凭借高超的技术,当机立断:内存条坏了。但是又苦于所爱隔山水啊,所以他只能当远程指挥官了。他指导姑娘:扒开电脑主机后盖,把内存条扯出来,然后开机看看,如果还蓝屏,那就把那条内存条插回去,把另一条拔出来。一顿操作猛如虎,姑娘在小伙无私又认真的指挥下,把电脑修好了。

过两天,姑娘又打电话给小伙子,说她收音机坏了,希望小伙能再远程指导一次。但是这次小伙无能了,他不行了,他不会,太难了。他放弃了,他把电话挂了。姑娘很失望。

但是姑娘不知道,电脑,是松耦合,强内聚的,哪个部件坏了就换哪个,但是收音机不一样,收音机是紧耦合的,牵一发而动全身,收音机没声音,可能是扩音器坏了,可能是信号接收其坏了,可能是解频罢工了···毕竟她是外行嘛,悲催的小伙子。

那么,就要切入到我们的正题了,松耦合、强内聚的电脑,是怎么组装的呢?

像内存条这种东西啊,管你是哪家生产的,只要符合规格,再比如鼠标、键盘、电池(电池得配套),反正哪个部件坏了就换哪个部件。为什么这些部件不论插在哪一台电脑上都能使用呢?是这些部件配合电脑主板设计,还是电脑主板配合这些零部件设计呢?

想来答案已经很明确了。就拿CPU来说,CPU的对外都是针脚式或触点式的标准接口,只要接口设计好,内部再复杂和外界也没有关系。哪个主板要插CPU,那就得和CPU的接口对上。那么这时候如果电脑的内存条坏了,就不该成为你更换麦克风的理由。这不是开玩笑,要是收音机的外放坏了,可能得整部收音机脱胎换骨了。

PC的接口始终是有限的,但是软件设计得好,却可以不断地拓展的。

依赖倒置,让项目并驾齐驱

我们来思考一下依赖倒置对并行开发的影响。

如果两个类之间有依赖关系,只要定制出两者之间的接口(或抽象类),就可以独立开发了。就像我最近做的一个图书管理项目,只要合理地运用依赖倒置,便可以很好的将界面与后台数据访问解耦合,从而实现并行开发。

最佳实践

依赖倒置原则的本质就是通过抽象使得各个类或模块的实现彼此独立,不互相影响,实现模块之间的松耦合,我们怎么在项目中使用这个规则呢?只要通过以下的几个规则:

  • 每个类尽量都有接口或抽象类,或者抽象和接口二者都具备。
  • 变量的表面类型尽量是接口或者抽象类。
  • 任何类都不应该从具体类派生。
  • 尽量不要覆写基类的方法。
  • 结合里氏替换原则。

反正我以前是一条都没对上。

“依赖倒转原则”在小项目上很难体现出来。


接口隔离原则

什么是“接口隔离原则”?

它建立在“依赖倒置原则”之上,

它的定义有俩:

  • Client should not be forced to depend upon interfaces that they don't use.
  • 客户端不应该依赖于它不需要的接口。
  • The dependency of one class to another one should depend on the smallest possible interface.
  • 类之间的依赖关系应该建立在最小的接口上。

简单易懂啊,如果对前面那个原则有一定的把握。

建立单一接口,接口尽量细化。


接口要高内聚

什么是高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。比如说你告诉你的保镖,今天去给我买一打爱马仕,他就去了。你也不用问他花了多少钱,他也不用问你是不是抽风了,这种不问条件执行的行为就是高内聚。

接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也越大,同时也有利于降低成本。

最佳实践

代码语言:txt
AI代码解释
复制
 - 一个接口只服务于一个子模块或业务逻辑
 - 通过业务逻辑压缩接口中的public方法,接口要勤快点重构
 - 已经被污染的接口,尽量去修改
 - 了解环境,拒绝盲从

迪米特法则

松耦合的法则:迪米特法则

英文解释:Only talk to your immedate friends.

只与直接的朋友通信。

如果两个类之间不能直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则首先强调在类的设计上,每一个类都应该尽量降低成员的访问权限,强调了类之间的松耦合。

类之间的耦合越弱,越有利于重复利用,一个处在弱耦合的类被修改,不会对相关类造成波及。

开-闭原则

何为“开闭原则”

Software entities like classes, modules and functions should be open for extension but closed for modifications.

一个软件实体,应该对拓展开放,对修改关闭。

抽象实体:

代码语言:txt
AI代码解释
复制
项目或软件产品中按照一定的逻辑规则划分的模块。
抽象类
方法

这个原则很重要,后面会很经常见。

多说无益,我就稍微说两句,后面慢慢看它真面目。

如何应对需求变化?

既然说,对修改要关闭,那需求变化了怎么办?

有如下方法:

代码语言:txt
AI代码解释
复制
1、修改接口
2、修改实现类
3、通过拓展实现变化

至于为什么需要这个原则、如何使用、何时使用这个原则,跟着我的步伐,往后看。


今天的分享到此告一段落,算是我回归设计模式模块的礼物。

在这里插入图片描述
在这里插入图片描述

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ThinkPHP-PHP开发中的主流框架
PHP 中的框架是什么? 框架就是通过提供一个开发 Web 程序的基本架构,PHP 开发框架把 PHPWeb 程序开发摆到了流水线上。换句话说,PHP 开发框架有助于促进快速软件开发(RAD),这节约了开发时间,有助于创建更为稳定的程序,并减少开发者的重复编写代码的劳动。 框架专门用于为这些常用元素(数据库交互、表示层、应用程序逻辑)提供结构,以便可以花费更少的时间来编写数据库接口代码或者表示层接口,而花费更多的时间来编写应用程序本身。以这种方式分解应用程序,这种架构被称为模型-视图-控制器(Mod
沈唁
2018/05/24
3K0
PHP全栈学习笔记20
thinkphp概述,thinkphp项目构建流程,thinkphp项目结构,thinkphp配置,thinkphp控制器,thinkphp模型,thinkphp视图,thinkphp的内置模板引擎。
达达前端
2019/07/03
2.1K0
PHP全栈学习笔记20
thinkphp常用配置config
下载解压 ThinkPHP 3.2.3,在默认的应用 Application(./Application) 中,包含一个默认的模块 Home(./Application/Home)。
PM吃瓜
2019/08/12
3.1K0
thinkphp常用配置config
Thinkphp5学习笔记
​ ThinkPHP5.0的URl访问受路由决定,如果关闭路由或者没有匹配路由的情况下,则是基于:
全栈程序员站长
2022/07/13
2K0
tp3.1.2缓存,日志,调试,模板,标签,视图
1.模板 默认在tpl目录下 默认后缀是.html,可以通过TMPL_TEMPLATE_SUFFIX来配置 如果启用分组,那么模板可能在tpl/分组名/目录下,可以配置TMP_FILE_DEPR来简化模板目录层次 2.赋值 $this->assign(‘name’, $name); 3.模版渲染 调用当前模块下当前操作$this->display(); 调用当前模块下的其他操作$this->display(‘user’);//当前在index,注意不要带后缀 调用其他模块下的操作$this->
苦咖啡
2018/05/08
1.5K0
PHP-ThinkPHP框架学习
每个项目都有一个独立的配置文件(位于项目目录的Conf/config.php),配置文件的定义格式均采用PHP返回数组的方式,例如:
偏有宸机
2020/11/04
7.2K0
TP3.2升级TP5踩到的坑
TP5: M 方法 替换为 Db::name、S 方法 替换为 session、I 方法 替换为 input、U 方法 替换为 url
黄啊码
2020/05/29
2.7K0
Thinkphp框架的项目规划总结和踩坑经验
1、项目分为PC端、移动端、和PC管理端,分为对应目录为 /Application/Home,/Application/Mobile,/Application/Admin;
PM吃瓜
2019/08/12
2.7K0
Thinkphp框架的项目规划总结和踩坑经验
[ThinkPHP6.*安装 (草稿先发布,再维护)
ThinkPHP6.0的安装,官方文档中有详细的说明,不过在安装之前,大家还是要做一些准备的,就是PHP本地开发环境 的搭建。
landv
2019/08/20
1.3K0
thinkjs学习笔记
IMWeb前端团队
2017/12/29
1.3K0
Thinkphp6学习笔记,持续记录
由此开始:https://www.kancloud.cn/manual/thinkphp6_0/1037479
房东的狗丶
2023/02/17
2K0
入坑!通过ajaxreturn jquery json提交form
\Think\Controller类提供了ajaxReturn方法用于AJAX返回数据给客户端(视图、模板、js等)。并且支持JSON、JSONP、XML和EVAL四种方式给客户端接受数据(默认JSON)。
PM吃瓜
2019/08/12
5.5K0
入坑!通过ajaxreturn jquery json提交form
thinkphp 路由
http://localhost:8082/admin/blog/23/ 此时会匹配23内容
mySoul
2019/05/30
1.4K0
Thinkphp
thinkphp:mvc模式 1,thinkphp的安装配置 条件 PHP>=5.4.0 PDO MbString CURL PHP Externsion Mysql Apache或Nginx 安装: composer composer config -g repo.packagist composer https://packagist.phpcomposer.com composer create-project --prefer-dist topthink/think think_co
Dean0731
2020/05/11
2.5K0
thinkphp创建应用的一般流程
下载完成后,解压,将文件里的ThinkPHP文件夹复制,我们在XAMPP/htdocs目录(服务器或者本地web目录)下新建一个文件bookstore文件夹,再将ThinkPHP文件夹拷贝到bookstore文件夹路径下
PM吃瓜
2019/08/13
1.6K0
ThinkPHP5框架与ThinkPHP3.2的对比区别
今天周一,又有一位新同事入职。正好大牛说要更新框架,最后确定了升级框架,原先使用的 ThinkPHP3.2 版本的,现在确定升级为 5 系列。应该庆幸没选择其他框架,什么 CI、YII、Laravel 之类的,Laravel 了解过一些,但是没深入过,还是 TP 系列使用的顺手一些。 ThinkPHP5 系列,十二载初心不改,值得信赖的 PHP 框架,十二周年献礼版本! ThinkPHP5.1 在 5.0 的基础上对底层架构做了进一步的改进,引入新特性,并提升版本要求。另外一个事实是,5.1 版本看起来对开
沈唁
2018/05/24
4.2K0
ThinkPHP控制器-精华总结
TP3.23对控制器做了更加细致的分层,除了默认的Controller层,还可以自定义事件控制层Event。
PM吃瓜
2019/08/12
1.2K0
ThinkPHP控制器-精华总结
控制器操作【2】
三.跳转和重定向 ThinkPHP 在操作数据库时,需要跳转和重定向页面。ThinkPHP 提供了一组方法来解决了这个问题。 //成功和失败的跳转 class UserController extends Controller { public function index() { $flag = true; if ($flag) { //会跳转到:http://localhost/demo39/User/all $this->success('新增成功!', '../User/all'); } else { //会跳转到本页的上一页 $this->error('新增失败!'); } } } PS:success()方法和 error()方法,第一个参数是提示信息、第二个跳转的地址、第三个跳转时间。默认情况下 success()方法是 1 秒,error()方法是 3 秒。
PM吃瓜
2019/08/13
6250
ThinkPHP5开发的正确姿势
安装篇 使用composer,既然是趋势就早日拥抱,能写PHP的这点工具用不来说不过去(另外官方的所有扩展都会以composer方式提供); 如果只需要核心单独安装核心框架就行了,应用仓库并非必须; 如果你安装的是dev-master,composer更新的也是开发版,如果安装的是正式版那么更新的也是最新的正式版(就和Chrome的开发版和正式版一样); 把web根目录指向public目录而不是根目录; 资源文件不要放到public目录以外; TP5完美支持PHP7,不要以为基于PHP7写的框架才会
超级小可爱
2023/02/23
1.1K0
CI基础知识笔记
1.知识点 $config[‘url_suffix’] = ”;//url后缀 $config[‘enable_query_strings’] = FALSE; $config[‘controller_trigger’] = ‘c’;//类似Thinkphp当中的m,可以传递c=news控制器名 $config[‘function_trigger’] = ‘m’;//类似Thinkphp当中的a,可以传递a=index方法名 $config[‘directory_trigger’] = ‘d’;
苦咖啡
2018/05/08
1.5K0
相关推荐
ThinkPHP-PHP开发中的主流框架
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档