前言
其实没有设计模式我们也能完成开发工作。但是为什么需要设计模式呢?让你看起来很牛,没错这个算一个。让你的代码层次感分明,可读性强而且容易维护。让你像我一样有更多的摸鱼划水时间。
可能有人说我一个类或者方法就干完的东西,你搞了七八个。当然使用设计模式也是要斟酌的。一些简单稳定的业务也不推荐使用设计模式。设计模式多用于复杂多变的业务或者要求适配性、扩展性更强的场景中。不要为了设计模式而设计模式。
接下来我们结合实际开探讨一下设计模式的一些原则。
1、开闭原则
public class Seller { public BigDecimal sellCar(Car car) { return car.getPrice(); } }
上面模拟4S店一个销售在卖车。突然老板搞了一个促销:在双十一要开展打折活动。在sellCar方法内增加一个计算可行吗?这势必影响整个业务,导致所有车都打折。不行不行!那么在Car里面操作?然后你改啊改!结果各种逻辑流程判断。才实现了业务要求。如果后续打折活动结束了或者升级了,你还要再进行各种改动。你发现一个打折让你的代码面目全非、臃肿不堪。上面说了对于复杂而多变的业务使用设计模式就可以解决。
那么设计模式最重要的一个原则就是开闭原则。也就是说一个软件模型实体如类、模块和函数应该对扩展开放,对修改关闭。也就是需要我们将业务行为抽象出来,使用抽象来构建。具体的业务通过抽象的实现来解决。那么我们就搞一个DiscountCar来extends Car.这样sellCar是什么具体的实现就执行什么具体的逻辑。不会影响以前的逻辑,而且不会因为改动原来的代码影响其他逻辑。保证接口可靠性和稳定性。如下:
public class DiscountCar extends Car{ private BigDecimal price; private BigDecimal discount; @Override public BigDecimal getPrice() { return price.multiply(discount); } }
2、依赖倒置原则
还拿上面的例子来说。经过一系列的打折活动4S店的生意蒸蒸日上。老板突然想扩展一下周边,同时压榨一下销售。让他们卖车的同时卖点玻璃水、防冻液之类的。这个需求当然又抛给了苦逼的程序员。sellCar太具体了不能满足需要了。很多情况下你会增加一个卖玻璃水、卖防冻液的方法。如果以后增加了卖大米,甚至买起了鸡蛋饼呢?总不能一直增加方法吧。我们需要考虑这种问题。我们可以抽象所有卖东西的场景。然后我们把卖的物品抽象成了一个抽象化的概念(java对应的是接口,把卖的行为抽象成了sell方法:
public interface Any { String getName(); BigDecimal getPrice(); } public class Seller { public BigDecimal sell(Any any) { return any.getPrice(); } }
这样随便老板以后卖什么你都可以通过该方法进行处理了,只需要关注于Any的实现。
3、职责单一原则
4S店销售卖了一段东西后,发现对客户的吸引力度不大。突然脑子比较灵活的老板又想起了电影中的一句台词:少林功夫加唱歌跳舞有没有搞头?对啊你们销售能不能搞搞什么唱、跳、Rap,当然打篮球就不要了别砸坏了车玻璃。但是人与人是不一样的,有的人只会唱,有的人只会跳,有的人可能唱跳Rap都会甚至篮球都很溜。所以为了适配这么多情况,我们必须把每种技能独立出来,根据不同的人来组合这些技能。
public class Seller implements Sing, Jump, Rap { public BigDecimal sell(Any any) { return any.doSell(); } @Override public void sing() { System.out.println("seller sing "); } @Override public void jump() { System.out.println("seller jumping "); } @Override public void rap() { System.out.println("seller raping "); } }
但是注意一定要适度,根据业务来细分。否则会导致接口过多反而增大开发难度以及代码的复杂度。
4、迪米特法则
新的销售方法搞了一段时间后,老板想看看检验一下他这个馊主意的效果。于是就叫了一个销售让他提供一份报表出来看看。那么程序员该如何实现老板查看报表功能呢,很可能有人会这么写:
public class Boss { private Seller seller; private Report report; public void read() { seller.apply(report); } }
乍看功能实现了,细看会发现逻辑不对。哪里不对呢?老板已经持有了报表,如果老板已经知道了你的业绩还叫你干什么?这种逻辑肯定是不对的!也就是说Boss直接依赖了Report;而这个Report不应该直接由Boss处理,而应由Seller控制。
public class Boss { private Seller seller; public void read(){ seller.apply(); } } public class Seller { private Report report; public void apply(){ report.show(); } }
这种最大化隔离了类与类之间的关系。降低了类之间的耦合。迪米特法则因此又得名最少知道原则。
5、接口隔离原则
用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。一个类对一个类的依赖应该建立在最小的接口上。
建立单一接口,不要建立庞大臃肿的接口尽量细化接口,接口中的方法尽量少,尽量细化接口。注意适度原则,一定要适度。不能滥用
就像上面的唱跳 rap,分离是最好的。
6、里氏代换原则
这里主要针对类的继承关系而言。比较正式的定义:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2 时,程序P的行为没有发生变化,那么类型 S 是类型 T 的子类型。
在4S店老板眼里,只要新来的能在销售岗位上像销售老手一样卖出汽车,他就是一名合格的销售。感觉这种定义就像一句名言:不管你黑猫白猫,能抓老鼠的都是好猫。
从某种含义上里氏代换有着以下的契约:
1. 子类必须完全实现父类的方法。父类出现的地方子类都可以代替父类。
2. 子类可以有自己的个性定义。里氏替换原则 可以正着用,但是不能反过来用。在子类出现的地方,父类未必就可以胜任。子类一般比父类有个性。
3. 覆盖或实现父类的方法时输入参数可以被放大。如果4S店老板规定基础车谈价的折扣最多九折,销售打个九五折没有问题,打八折老板肯定要跟你说道说道了。
4. 覆写或实现父类的方法时输出结果可以被缩小。同样是15W本来只能卖出给客户一个乞丐版,结果换了个销售结果给出了一辆旗舰版。怕不是过不了试用期哦。
7、合成/复用原则
它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
总结
这七种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中,开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。在实际开发中我们可以根据业务来进行设计模式的使用,但是很重要的一点千万不要被这些条条框框束缚了你的手脚。
最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!
 

Java设计模式的7种设计原则还有很多人不知道的更多相关文章

  1. JAVA设计模式总结之六大设计原则

    从今年的七月份开始学习设计模式到9月底,设计模式全部学完了,在学习期间,总共过了两篇:第一篇看完设计模式后,感觉只是脑子里面有印象但无法言语.于是决定在看一篇,到9月份第二篇设计模式总于看完了,这一篇 ...

  2. Java设计模式面试题 01 - 六大原则

    Java设计模式面试题 01 - 六大原则 1. 单一职责原则 Single Responsibility Principle SRP原则 分清职责,接口一定要做到单一职责,方法也要做到,类尽量做到 ...

  3. 适用于Java开发人员的SOLID设计原则简介

    看看这篇针对Java开发人员的SOLID设计原则简介.抽丝剥茧,细说架构那些事——[优锐课] 当你刚接触软件工程时,这些原理和设计模式不容易理解或习惯.我们都遇到了问题,很难理解SOLID + DP的 ...

  4. C#七种设计原则

    在C#中有七种设计原则 分别是 1.开闭原则(Open-Closed Principle, OCP) 2.单一职责原则(Single Responsibility Principle) 3.里氏替换原 ...

  5. java设计模式学习笔记--单一职责原则

    单一职责原则注意事项和细节 1.降低类的复杂度,一个类只负责一项职责 2.提高可读性,可维护性 3.降低变更引起的风险 4.通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单 ...

  6. C#设计模式学习笔记:设计原则

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8287784.html,记录一下学习过程以备后续查用. 写代码也是有原则的,我们之所以使用设计模式,主要是为了 ...

  7. java设计模式学习笔记--接口隔离原则

    接口隔离原则简述 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应建立在最小的接口上 应用场景 如下UML图 类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类 ...

  8. java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

    在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...

  9. Java设计模式01:设计模式的 分类 和 设计原则

    一.总体来说设计模式分为三大类: 创建型模式:对象的创建. 创建对象本身是比较耗时的操作,所以我们这里专门找人来帮我们创建对象,我们根据经验总结出来的设计成熟的思路模式. 结构型模式:对象的组成(结构 ...

随机推荐

  1. ArcGIS API For Javascript :如何动态生成 token 加载权限分配的地图服务?

    一.需求 项目中我们通常会遇到为外协团队.合作友商提供地图服务的需求,因此对地图服务的权限需要做出分配. 二.现状 主流的办法是用用户和角色来控制,通常使用代理方式和用户名密码的方式来实现. 三.思路 ...

  2. 初识JVM内存模型

    计算机内存模型 在程序运行时,CPU通过访问主存获取数据,但随着CPU的快速发展,CPU访问速度越来越高,硬件无法满足CPU的条件下,大多内存加入了高速缓存机制,不同CPU都有对应的多级(一般为三)缓 ...

  3. opencv 5 图像转换(2 霍夫变换)

    霍夫线变换 标准霍夫变换和多尺度霍夫变换(HoughLines()函数) 实例: #include <opencv2/opencv.hpp> #include <opencv2/im ...

  4. href=”javascript:void(0);

    href=”javascript:void(0);”这个的含义是,让超链接去执行一个js函数,而不是去跳转到一个地址,而void(0)表示一个空的方法,也就是不执行js函数. 为什么要使用href=” ...

  5. 带你涨姿势的认识一下 Kafka 消费者

    之前我们介绍过了 Kafka 整体架构,Kafka 生产者,Kafka 生产的消息最终流向哪里呢?当然是需要消费了,要不只产生一系列数据没有任何作用啊,如果把 Kafka 比作餐厅的话,那么生产者就是 ...

  6. ArcGIS 重新创建几何服务(GeometryService)

    #参考官方网址:http://enterprise.arcgis.com/zh-cn/server/10.4/administer/windows/re-creating-the-geometry-s ...

  7. "PSP助手”微信小程序宣传视频链接及内容介绍

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/8677] 队名:扛把子组 组长:迟俊文 组员:刘信鹏 韩昊 宋晓丽 梁梦 ...

  8. 网络爬虫一定要用代理IP吗

    数据采集现在已经成为大数据时代不可以缺少的一部分,在数据采集过程中,很多人都会用到代理ip,那么网络爬虫一定要用代理IP吗?答案虽然不是肯定的,但出现以下情况一定是需要用到代理IP的.1.在爬虫的时候 ...

  9. 《手把手教你》系列练习篇之2-python+ selenium自动化测试(详细教程)

    1. 简介 今天我们还是继续练习练习基本功,各位小伙伴要耐住住性子,要耐得住寂寞啊,不要急躁,后面你会感谢你在前边的不断练习的.到后面也是检验你前边的学习成果的一次很好实践. 本文介绍如何通过link ...

  10. 【NHOI2018】扑克游戏

    [问题描述] 有一种别样“小猫钓鱼”扑克游戏.有 N 张牌,每张牌都有一个花色和点数.游戏的规则:扑克接龙时,若前面有同样花色的牌,你可以将这两张牌连同之间的牌都取走,得到的分值为取走牌点数之和.这里 ...