优雅密码,如亭亭玉立的美人,赏心悦目。但糟糕的代码就像一堆狗屎,让人望而却步。如何写出优雅的代码?那么你必须理解并熟悉这6条设计原则的应用:开闭原则、单一职责原则、接口隔离原则、Dimiter原则、Liskov替换原则、依赖倒置。在本文中,我们将通过代码演示让大家轻松理解这6条代码设计原则。加油~1.开闭原则开闭原则是对扩展开放,对修改关闭。对于扩展和修改,我们怎么理解呢?扩展开放意味着未来业务需求会快速变化,代码要保持灵活性和适应性。Modificationclosed表示不允许在原类中进行修改,保持稳定性。因为每天的需求都是迭代更新的,所以我们经常需要修改原来的代码。如果代码设计不好,可扩展性不强,每次需求迭代都要修改原代码,很可能引入bug。因此,我们的代码应该遵循开闭原则,即对扩展开放,对修改关闭。为了方便大家理解开闭原理,我们来看一个例子:假设有这样一个业务场景,大数据系统推送文件,根据不同的类型采用不同的解析方式。大部分小伙伴都会写如下代码:if(type=="A"){//按照A格式解析}elseif(type="B"){//按照B格式解析}else{//按照默认格式解析}这段代码有什么问题?如果分支很多,这里的代码就会变得臃肿,难以维护,可读性低。如果需要接入新的分析类型,只能修改原来的代码。显然,增加或删除某个逻辑,需要修改原类的代码,这就违反了开闭原则。为了解决这个问题,我们可以使用策略模式对其进行优化。可以先声明一个文件解析的接口,如下:publicinterfaceIFileStrategy{//是哪种类型的文件解析,A还是B//封装的公共算法(具体解析方法)voidresolve(Objectparam);}然后实现不同的文件解析策略,比如A类解析:文件_A_RESOLVE;}@Overridepublicvoidresolve(Objectobjectparam){logger.info("类型分析文件,参数:{}",objectparam);//A类型解析具体逻辑}}如果以后需求发生变化,比如增加或者删除某个逻辑,不会修改到原来的类,只需要修改对应??文件解析类型的类即可。2.单一职责原则SingleResponsibilityPrinciple:一个类或者一个接口最好只负责一个职责。假设类C违反单一原则,它负责两个职责P1和P2。当职责P1需要修改时,会改为C类,可能会影响到原来正常的P2。如何更好地理解它?比如你实现一个图书馆管理系统,如果一个类包含图书和读者的增删改查,你可以认为这个类违反了单一原则。因为这个类涉及到不同的功能责任点,所以可以拆分这个。上面图书馆管理系统的例子违反了单一原则,按业务拆分。这样比较容易理解,但是有时候,一个类并不是那么容易区分的。这时候你可以看这个标准来判断功能职责是否单一:类中的私有方法太多,你很难给类起一个合适的名字。类中代码、函数或属性的行数过多。是因为集中操作类中的某些属性类依赖太多其他类,或者依赖类中其他类太多。比如你写了一个方法,包括日期处理和借还书的业务操作,你可以把日期处理抽取出来一个私有方法。然后,如果你发现很多私有方法和日期处理类似,你可以把这个日期处理方法提取到一个工具类中。在日常开发中体现单一原则的思想。比如微服务拆分。3、接口隔离原则接口隔离原则:不应该强迫接口的调用者或使用者去依赖它不需要的接口。要求建立单一的接口,不要创建大而臃肿的接口,尽量细化接口,接口中的方法尽量少,让接口只包含客户端(调用者)是的方法即一个类对另一个类的依赖应该建立在最小的接口上。例如,A类通过接口I依赖于B类,C类通过接口I依赖于D类。如果接口I不是A类和B类的最小接口,那么B类和D类必须实现它们的方法不需要。.如下图:这张图表达的意思是A类依赖接口I中的method1和method2,B类是依赖A类的实现。C类依赖接口I中的method1和method3,类D是对类C的依赖的实现,对于实现类B和D,它们都有未使用的方法,但是因为实现了接口I,所以必须实现这些未使用的方法。你可以看下面的代码:publicinterfaceI{voidmethod1();无效方法2();voidmethod3();}@ServicepublicclassA{@Resource(name="B")privateIi;publicvoiddepend1(){i.method1();}publicvoiddepend2(){i.method2();}}@Service("B")publicclassBimplementsI{@Overridepublicvoidmethod1(){System.out.println("ClassBimplementsmethod1ofinterfaceI");}@Overridepublicvoidmethod2(){System.out.println("B类实现接口I的方法2");}//这个方法没有用到,但是必须默认实现,因为我有这个接口方法@Overridepublicvoidmethod3(){}}@ServicepublicclassC{@Resource(name="D")privateIi;publicvoiddepend1(Ii){i.method1();}publicvoiddepend3(Ii){i.method3();}}@Service("D")publicclassDimplementsI{@Overridepublicvoidmethod1(){System.out.println("ClassDimplementsinterfaceIMethod1");}//这个方法没有用到,但是必须默认实现,因为我有这个接口方法@Overridepublicvoidmethod2(){}@Overridepublicvoidmethod3(){System.out.println("类D实现接口I的方法3");}}你会发现,如果接口过于臃肿,只要接口出现了Method,无论是否为依赖它的类使用,实现类都必须实现这些方法。实现类B没有使用method3,它也有一个默认实现。实现类D没有使用method2,它也有默认实现。显然,这不是一个好的设计,违反了接口隔离原则。我们可以拆分接口I,拆分设计如图2所示:接口是不是越细越好?并不真地。在日常开发中,在使用接口隔离原则对接口进行限制时,要注意以下几点:接口尽量小,但要有一个限度。界面细化可以提高程序设计的灵活性,这是不可否认的事实,但如果界面太小,又会造成界面过多,使设计复杂化。所以一定要适度地做。为依赖接口的类定制服务,只将它需要的方法暴露给调用类,隐藏它不需要的方法。只有专注于为模块提供定制服务,我们才能建立最小的依赖关系。提高凝聚力,减少外部互动。让接口用最少的方法完成最多的事情。使用接口隔离原则,一定要适度,接口设计过大或过小都不好。在设计界面时,只有花更多的时间思考和规划,才能准确地实践这一原则。4.得墨忒尔定律的定义:又称最少知识原则。一个类对其他类的了解越少越好,也就是说一个对象对其他对象的了解越少越好,只和朋友交谈,不和陌生人交谈。其核心思想是尽量减少类之间的耦合,尽量减少代码修改对原有系统的影响。举个生活中的例子:你肯定对你的对象很了解,但是如果你对别人的对象也很了解,如果你的对象知道了,那么就会有大事发生。让我们看下一个违反迪米特定律的例子。业务场景如下:某学校要求打印出所有师生的身份证。//学生类Student{privateStringid;publicvoidsetId(Stringid){this.id=id;}publicStringgetId(){返回id;}}//教师类Teacher{privateStringid;publicvoidsetId(Stringid){this.id=id;}publicStringgetId(){返回id;}}//manager(monitor)publicclassMonitor{//所有学生publicList
