面试官:你不懂六大设计原则,回去等通知吧!

一、前言

不知道大家是否有这样的体会,就是在学习设计模式的时候,看了很多书籍,也照着很多示例把每个模式挨个敲了几遍,但过了一段时间后,就会忘了一大半。或者有的朋友尝试在业务编码中使用,却越用越复杂,本来一个类几个方法能搞定的业务,套用模式后会多出好多接口和类,所以用着用着就放弃了。我说的比较直接点,很多教材或博客中使用Animal、Fruit、Car这些例子来教设计模式,初衷是好的,但真没多大用,甚至会误人子弟。

最近笔者再次学习了设计模式(不知道是这些年的第多少次了),突然有了些感悟。我尽量用最简单通俗的语言描述出我想表达的,有的观点可能比较偏激或不太适合所有人,但如果大家能从这篇文章中GET到一两个点,那也值了,哈哈。

    下面我先以我个人的想法简单粗暴地理解一下设计模式的六大原则。Show Time!

二、六大原则

2.1、单一职责原则

  • 官方解释:单一职责原则(SRP:Single responsibility principle)又称单一功能原则,面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的原因。

  • 大白话:一个类只有一个发生变化的原因,我只能说在业务编码中不太可能,或很维做到。其实大家不必纠结于有几个让类发生变化的原因。个人建议你想实践单一职责原则,最好先养成良好的编码规范,如果你平时写代码,一个类里不管什么业务方法都往里塞,一个方法里嵌套着各种判断,再好的原则也帮不也你。

  • 实践:和类名不相关的业务不要放在这个类里,和方法名不相关的代码请拆成单独的子方法。还有当你在定义一个接口、类或方法的时候,从业务的角度用心地多想一下:这段代码放这里真的合适吗?

2.2、里氏替换原则

  • 官方解释:里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

  • 大白话:这个原则其实还是很好理解的,主要是约束子类的行为,要求其行为和基类保持一致,如果替换为子类后,程序运行不正常,则说明子类没有按基类的预期实现业务,或者说子类不适合继承这个基类,对不起,请找适合的基类继承。

  • 实践:如果子类从一个基类继承后,实现基类定义的虚方法时感觉很别扭痛苦的时候,请考虑一下是否一定要从这个基类继承。

2.3、依赖倒置原则

  • 官方解释:依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

  • 大白话:多用接口和抽象类,少用实现类(工具类除外)。大家看框架源码的时候应该能感觉到,大神在实现框架的时候到处都是接口或抽象类,而自己的代码却是一大片的实现类,其实直接用实现类是没有问题的。架构方法中有一句叫可扩展性,其实接口和抽象类就是实现可扩展性的基石。当需要扩展原有逻辑的时候,别人用接口和抽象类的直接加个新子类继承下,你用实现类的到处一大片一大片的改,请回答我,有没有?

  • 实践:写代码的时候多考虑扩展性,如果这段代码以后扩展或变化的可能性很高,请用接口或抽象类封装下,抽象出不变的接口,将变化的部分留给不同的实现类。

2.4、接口隔离原则

  • 官方解释:接口隔离原则(Interface Segregation Principle,)使用多个专门的接口比使用单一的总接口要好。一个类对另外一个类的依赖性应当是建立在最小的接口上的。

  • 大白话:这个原则和单一职责原则有点象,好吧,其实很难区分的。主要区分点在“职责”和“隔离”两个词上。职责要求按类的功能单一性定义接口、类、方法。隔离要求最细化的定义接口,尽量避免大而全的接口,不然接口一改,所以的实现类一片报红,请回答我,有没有?

  • 实践:情愿让类实现多个单一接口,也不要实现一个大而全的接口。

2.5、迪米特原则

  • 官方解释:迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。 

  • 大白话:电视剧经常有这个台词:“你知道的太多了”,然后一枪被崩了。这个原则也是这个道理,就是一个类尽量减少和其他类组合,这样能减少类之间的耦合,如果实现要关联,可以通过第三者(朋友)。门面模式和中介者模式就是这个原则的体现。

  • 实践:一个类里,尽量减少与太多的类接触,如果不可避免,可以用一个中介类代替。

2.6、开闭原则

  • 官方解释:在面向对象编程领域中,开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用质量的过程。遵循这种原则的代码在扩展时并不发生改变,因此无需上述的过程。

  • 大白话:其实这个原则实操性不强。如果这个原则是思想的话,上面的五个原则就是这个思想的实践,如果我们代码真的能做到职责单一、面向抽象编程且清爽的编码规范,则会很容易实现开闭原则。但现实情况是,我们的代码模块与模块,类与类高度耦合、很难见到接口或抽象类、甚至全是面向过程编码。所以在实际业务中,我们改一点代码,都要涉及很多项目、类、方法。改完很自信地说:我改动不大,不会影响线上业务的,不用测试,直接上线。请回答我,有没有?

  • 实践:尽量避免修改原有的代码(一点不改也不太可能),前期编码的时候留好扩展点,使用继承增加新子类的方式修改原有业务。

三、总结

  • 在学习设计原则和模式的时候,请先保证自己写出的代码是整洁且符合规范的,不然再好的原则和模式也拯救不了你那一大坨一大坨的类和方法,最起码的读你写的某一个方法的时候,不用拖滚动条。

  • 真正的理解你所在公司的业务和需求,先在产品和文档级别上简化业务、理清编码的思路,这样更准确地找出业务的变化点和扩展点。

  • 设计模式其实就是封装变化,所以编码的时候多用心变化点,有变化了就考虑抽象出接口或抽象类。当然,在实际业务中,多是增删改查,如果一昧的到处定义接口,也会增加复杂度,这些可以自己权衡或按团队的编码规范实施。

  • 不要刻意地去背这些模式或者照着敲几遍,没用的!实际业务编码中,发现业务变化或扩展点后再去找适合的模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dollar Dayz POJ - 3181(动态规划+大数高低位分离输出)

题意:就是给出二个数N,和k,有1~k种钱币,每种都 是无限个,用这些种类的钱币可以组合成总钱N有多少种方式。 解题:这就是一个完全背包,把N看成容量,钱币的类型值为 花费和价值。与记录…

[PAT乙级]1007 素数对猜想

让我们定义d​n​​为&#xff1a;d​n​​p​n1​​−p​n​​&#xff0c;其中p​i​​是第i个素数。显然有d​1​​1&#xff0c;且对于n>1有d​n​​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。 现给定任意正整数N(<10​5​​)&#xff0c;请计…

is this mysql server_Mysql:is not allowed to connect to this MySQL server

如果你想连接你的mysql的时候发生这个错误&#xff1a;ERROR 1130: Host 192.168.1.3 is not allowed to connect to this MySQL server解决方法&#xff1a;1。 改表法。可能是你的帐号不允许从远程登陆&#xff0c;只能在localhost。这个时候只要在localhost的那台电脑&#…

Asp.Net Core Filter 深入浅出的那些事-AOP

一、前言在分享ASP.NET Core Filter 使用之前&#xff0c;先来谈谈AOP,什么是AOP 呢&#xff1f;AOP全称Aspect Oriented Programming意为面向切面编程&#xff0c;也叫做面向方法编程&#xff0c;是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统…

C++函数模板和普通函数的调用规则

C函数模板和普通函数的调用规则: 普通函数可以进行自动类型转换。 函数模板必须严格类型匹配。 C编译器优先考虑普通函数。 如果函数模板可以产生一个更好的匹配&#xff0c;那么选择模板。 可以通过空模板实参列表的语法限定编译器只能通过模板匹配。 代码如下&#xff…

A Mini Locomotive POJ - 1976(动态规划+思维)

题意&#xff1a;有三个火车头&#xff0c;n个车厢&#xff0c;每个车厢里面对应的有一定的人数。规定每个火车头最多 拉m个连续的车厢而且他们拉的车厢一定是从左到右连续的&#xff0c;问它能够拉的最多的人数&#xff1b; 思路&#xff1a;类似01背包的解法&#xff0c;首先…

mysql如何管理innodb元数据_MySQL 8 InnoDB 集群管理

使用 dba.checkInstanceConfiguration()在添加实例到集群中前&#xff0c;使用该方法检查实例配置是否满足InnoDB 集群要求。使用 dba.configureLocalInstance() 配置实例在MySQL Server版本不支持持久化功能的实例上&#xff0c;需要使用该方法添加修改配置信息到本地实例的选…

c编译过程概述

index.cpp是如何变成index.exe&#xff1f; 过程如下: #mermaid-svg-TCJ1Rm4qFgAObpkX .label{font-family:trebuchet ms, verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-TCJ1Rm4qFgAObpkX .label text{fill:#333}#mermaid-svg-T…

.NET Core技术研究-通过Roslyn代码分析技术规范提升代码质量

随着团队越来越多&#xff0c;越来越大&#xff0c;需求更迭越来越快&#xff0c;每天提交的代码变更由原先的2位数&#xff0c;暴涨到3位数&#xff0c;每天几百次代码Check In&#xff0c;补丁提交&#xff0c;大量的代码审查消耗了大量的资源投入。如何确保提交代码的质量和…

FATE HDU - 2159(二维完全背包)

限制条件&#xff1a; 1.忍耐度 m 2.杀怪个数 s 构造&#xff1a; dp[m][s] 得到的经验值 Time limit 1000 ms Memory limit 32768 kB OS Windows Source 2008信息工程学院集训队——选拔赛 最近xhd正在玩一款叫做FATE的游戏&#xff0c;为了…

mysql数据库check命令_利用mysqlcheck命令快速修复mysql数据库

表索引异常,修复msql表索引(表引擎:myisam)myisamchk --safe-recover /usr/local/mysql/data/ename_news/dede_arccacherepair table customerquestion;Error infos: Table ./ename_news/dede_arccache is marked as crashed and should be repairedmyisamchk -r data/ename_ne…

python中类变量的访问方式_在Python中,如何访问类方法中的“静态”类变量

就像所有的好例子一样&#xff0c;你简化了你实际想要做的事情。这很好&#xff0c;但值得注意的是&#xff0c;python在类和实例变量方面有很大的灵活性。方法也是如此。为了获得很好的可能性&#xff0c;我建议阅读Michael Ftsch new-style classes introduction&#xff0c;…

[PAT乙级]1009 说反话

给定一句英语&#xff0c;要求你编写程序&#xff0c;将句中所有单词的顺序颠倒输出。 输入格式&#xff1a; 测试输入包含一个测试用例&#xff0c;在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成&#xff0c;其中单词是由英文字母&#xff08;大小写…

Cheapest Palindrome POJ - 3280(动态规划*)

题意&#xff1a; 给出一个字符串&#xff0c;要求将其修改成一个回文字符串&#xff0c;给出修改某种字母&#xff08;添加或删除&#xff09;的价值&#xff0c;求最小使其成为回文字符串的价值。 题解&#xff1a; 感觉是求最长回文子序列的变形&#xff0c;然而刚开始想着…

Blazor Blazor Blazor

Blazor 项目现在可以说是整个 .NET 社区最火的项目&#xff0c;但是它的起源却非常有趣&#xff0c;也可以说是见证了 .NET 社区的发展。2017年4月&#xff0c;一位英国光头小哥哥开始思考在 WebAssembly 下运行 .NET 的方法&#xff0c;这时他碰巧发现一个之前从未见过的 .NET…

C++函数模板机制结论

函数模板机制结论: 编译器并不是把函数模板处理成能够处理任何类型的函数函数模板通过具体类型产生不同的函数编译器会对函数模板进行两次编译&#xff0c;在声明的地方对模板代码本身进行编译&#xff0c;在调用的地方对参数替换后的代码进行编译。

python最大堆heapq_Python-堆的实现与heapq(最小堆库函数)

目录简介堆是一个二叉树&#xff0c;它的每个父节点的值都只会小于或大于所有孩子节点(的值)。它使用了数组来实现&#xff1a;从零开始计数&#xff0c;对于所有的 k &#xff0c;都有 heap[k] < heap[2*k1] 和 heap[k] < heap[2*k2]。 为了便于比较&#xff0c;不存在的…

深入浅出 ASP.NET Core 与 Docker 入门课程说明

点击蓝字“角落的白板报”关注我哟加个“星标★”&#xff0c;好文必达&#xff01;深入浅出 ASP.NET Core 与 Docker 入门课程说明《深入浅出 ASP.NET Core 与 Docker 》是一门新的课程&#xff0c;本课程所有的内容全部免费&#xff0c;以图文配合视频的形式呈现。课程完整视…

UVA10129 Play on Words (并查集判连通+欧拉回路)

题目解析&#xff1a; 输入一些英文单词&#xff0c;根据该单词的首尾字母&#xff0c;判断所有单词能不能连成一串&#xff0c; 类似于成语接龙的意思。同样如果有多个重复的单词时&#xff0c;也必须满足这样的条件才能通过&#xff0c; 否则都是不可能的情况。输入包括若干…

[PAT乙级]1010 一元多项式求导

设计函数求一元多项式的导数。&#xff08;注&#xff1a;x​n​​&#xff08;n为整数&#xff09;的一阶导数为nx​n−1​​。&#xff09; 输入格式: 以指数递降方式输入多项式非零项系数和指数&#xff08;绝对值均为不超过 1000 的整数&#xff09;。数字间以空格分隔。 …