java程序设计原则知多少
程序设计七大原则
一、开闭原则
针对我们设计的功能模块对扩展开放,对修改关闭:利用面向接口(抽象)编程(多态的特性),实现对功能需求扩展的同时,不允许更改原来的代码。提高对象的可复用性、可维护性、灵活性。
抽象的说,用抽象思维构建我们想要创建的实体对象,用具体实现去扩展实体对象的细节实现。
具体的说,业务需求的功能可以去扩展,但是已经实现的功能不应该去修改。
需求:以简单工厂模式和工厂方法模式理解开闭原则。
分析:
工厂模式是获取一个实例对象的建造者模式,我们不关心对象如何产生,只关心结果。
简单工厂模式是面对比较简单的业务场景,用于获取一个对象实例。我们需要传入相关业务参数,让简单工厂对象去做相应的判断,然后返回给我们对应的实例对象。这个工厂对象做了很多事情,他违背了单一职责原则,当我们的业务需要扩展的时候,这个工厂对象必须去修改,新增业务判断,新增返回对应的实例对象。这就违背了开闭原则。
public class FruitsFactory { /**
* @description:
* @param fruitsName
* @return com.lmc.gp13280.pattern.factory.fruits.IFruits
* @date 2019/5/23 15:44
* @author lmc
*/
public IFruits product(String fruitsName){ if(null != fruitsName && fruitsName != ""){
System.out.println("客户需求的水果是"+fruitsName);
if("苹果".equals(fruitsName)){
System.out.println("水果工厂生产了苹果");
return new Apple();
}
if("橙子".equals(fruitsName)){
System.out.println("水果工厂生产了橙子");
return new Orange();
}
if("香蕉".equals(fruitsName)){
System.out.println("水果工厂生产了香蕉");
return new Banana();
}
return null;
}else{
return null;
}
}
}
上面是一个水果工厂,我如果想要草莓,就必须的修改代码去实现草莓的生产了。
工厂方法模式是抽象一个工厂接口,让具体的工厂子类实例对象实现工厂接口。我们想要一个具体的实例对象,只需要找相应的子类工厂实现类就可以了,如果需要业务扩展,我们不需要修改原来的工厂子类,只需要新增新的工厂子类就行了。这就实现了业务扩展,但是不会修改原来的程序逻辑。遵循了开闭原则和单一职责原则。
public interface IFruitsFactory {
/**
* 工厂的生产方法
* @return IFruits
*/
IFruits product(); }
public class AppleFactory implements IFruitsFactory {
@Override
public IFruits product() { System.out.println("苹果工厂只生产苹果");
return new Apple();
}
}
public class BananaFactory implements IFruitsFactory {
@Override
public IFruits product() {
System.out.println("香蕉工厂只生产香蕉");
return new Banana();
}
}
public class OrangeFactory implements IFruitsFactory {
@Override
public IFruits product() {
System.out.println("橙子工厂只生产橙子");
return new Orange();
}
}
上面的示例代码中,我们要新增具体的水果工厂去扩展业务,只需要新增对应的工厂子类去实现水果工厂的接口就行了。
实现业务扩展,不改变原来的程序就是遵循开闭原则。
二、依赖倒置原则
spring的依赖注入相信大家都不陌生,其实依赖倒置原则是程序对象依赖其他对象的时候,应该依赖其抽象,不要依赖实现,应该依赖顶层对象,不要依赖具体的底层对象。因为程序的具体实现都是实现类去实现的,但是我们要去依赖实现类的顶层接口对象,这就是倒置,也就是依赖倒置。
依赖倒置原则的核心是运行时多态,程序在编译时不会去实例化子类对象,在程序运行的时候虚拟机才会去选择实例化具体的子类对象。
在程序设计中,一般接口定义好了,就不会去轻易改变。因为,在一个成熟的系统中,改变接口,就相当于把设计推翻重构了,你愿意做这样的事情?但是实现类,咱们可以进行轻微改动,或者说不改,新增一个新的实现类去代替。如果依赖其实现类,只要实现类改动,那么程序员的灾难是不是来了呢?如果依赖其顶层接口,我们其他依赖此接口的代码都不需要去做任何改动,因为接口没变啊,只需要改动需求具体的实现业务逻辑,或者新增业务子类实现接口。是不是可以提前下班了。
通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的
可读性和可维护性,并能够降低修改程序所造成的风险。
/**
* 水果店
* @author: maocheng.liao
* @create: 2020-02-23 15:20
*/
public class FruitShop {
private IFruitsFactory fruitsFactory;
public IFruitsFactory getFruitsFactory() {
return fruitsFactory;
}
public void setFruitsFactory(IFruitsFactory fruitsFactory) {
this.fruitsFactory = fruitsFactory;
}
/**
* @description:
* @param :从水果生产基地去进货水果
* @return com.lmc.gp13280.pattern.factory.fruits.IFruits
* @date 2020/2/23 15:34
* @author maocheng.liao
*/
public IFruits getFruits(){
IFruits fruits = fruitsFactory.product();
return fruits;
}
}
/**
* 水果店依赖倒置测试
*
* @author: maocheng.liao
* @create: 2020-02-23 15:25
*/
public class FruitShopTest {
public static void main(String[] args) {
IFruitsFactory fruitsFactory= new AppleFactory();
FruitShop fruitShop=new FruitShop();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits apple = fruitShop.getFruits();
apple.getName();
fruitsFactory = new BananaFactory();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits banana = fruitShop.getFruits();
banana.getName();
fruitsFactory = new OrangeFactory();
fruitShop.setFruitsFactory(fruitsFactory);
IFruits orange = fruitShop.getFruits();
orange.getName();
}
}
上面的代码就是最简单的依赖倒置的实现,我们依赖的是水果工厂接口和水果接口,水果店是在水果生产基地去进货水果,至于进货什么水果,取决于水果生产基地生产什么水果和水果店想进什么水果。而不是依赖具体的水果工厂实现类和具体的水果实现类。
- 注意:上述部分简单代码并未呈现,详细代码见博客地址:https://www.cnblogs.com/programmerkaixin/p/10918844.html
三、单一职责原则
我觉得单一职责是迪米特法则的一种体现。
单一职责原则:见名知意,专人做专事,不要多管闲事。对于类、接口、方法只负责一项自己的职责。对于自己的职责程序修改之后,不会影响到其的职责程序。高内聚,低耦合的程序必须遵循单一职责,分工明确,可读性、可维护性高。
最简单的示例:咱们人的手脚代替不了眼睛,眼睛也代替不了手脚。
臃肿这个词是不是能很好的体现出单一职责原则呢?代码写的这么臃肿,还能不能好好玩耍啦。
四、接口隔离原则
我觉得接口隔离原则是单一职责原则的一种体现,也是迪米特法则的一种体现。
面向对象编程,万物皆对象。
接口隔离原则:定义多个细化而明确分工的专门接口,不要去定义一个单一臃肿的接口。对于臃肿的接口,我们不好具体实现,这样肯定会违背单一职责原则。
最简单的示例:对于家用小汽车对象来说,往大的说,他属于交通工具类、他属于车类、它属于汽车类。往小的说,它属于家用小汽车类、私家车类。
五、迪米特法则
迪米特法则又叫最少知道原则,也有单一职责和接口隔离原则的味道。
迪米特法则:低耦合,如何做到极致呢,那就是只依赖自己真正有关系的对象。在我职责之外的对象全部拒之门外。
我觉得这个没啥好说的,做到了单一职责,迪米特法则很好实现吧。
六、里氏替换原则
官方定义:任何基类(父类)可以出现的地方,子类一定可以出现。 里氏替换原则是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系。
本人理解: 里氏替换原则是为了约束继承泛滥,就是说,在面向对象程序设计中,必须具有is-A的关系才能去使用继承,而不能去为了实现某一业务需求,为了方便使用继承而继承。
前置条件:每个方法调用之前,该方法应该校验传入参数的正确性,只有正确才能执行该方法,否则认为调用方违反契约,不予执行。这称为前置条件(Pre-condition)。
后置条件:一旦通过前置条件的校验,方法必须执行,并且必须确保执行结果符合契约,这称之为后置条件(Post-condition)。也就是返回值符合。
里氏替换原则约束条件:当存在继承关系时,子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松;而子类中方法的后置条件必须与超类中被覆盖的方法的后置条件相同或者更为严格。
不要为了继承而继承,而是真的有继承关系的时候才能去继承。
七、合成复用原则
这里结合依赖倒置原则使用合成复用原则效果更佳。
组合(has-a):类比电脑组装,内存、硬盘、cpu、显卡 ······ 它们之间组成了电脑,但是他们之间没有什么关系。这就是组合关系,生命周期一致。
聚合(contanis-a):类比员工聚合成部门。员工和部门是相互独立的,一两个员工离职不影响部门对象。部门解散也不影响员工对象。
合成复用原则:程序复用尽量使用组合关系、聚合关系。尽量少使用继承关系去实现业务需求。
继承会把所有的实现全部暴露给子类。破坏了类的封装性,父类的改变,会影响子类。高耦合。
组合、聚合可以很好的遵循依赖倒置原则,开闭原则。成员对象的细节实现(组合、聚合对象)对于一个新的对象是隐藏的。
合成复用原则配合依赖倒置原则,很好的遵循开闭原则。达到程序高可用、高可维、高可读。
spring为什么这么牛?spring为什么依赖注入?spring为什么是轻量级的?
java程序设计原则知多少的更多相关文章
- java程序设计原则
前言: 前言:java这种面向对象的的语言其实是很符合人的生活思维模式的,因为它以对象作为自己的研究对象,所谓"万物皆对象".一个人.一颗苹果.一只蚂蚁都是对象.所以它的设计原则和 ...
- 2016-2017-2 《Java程序设计》预备作业2总结
2016-2017-2 <Java程序设计>预备作业2总结 古希腊学者普罗塔戈说过:「头脑不是一个要被填满的容器,而是一束需要被点燃的火把.」 在对计算机系的学生情况的调查中,我说: 最近 ...
- 《程序设计教学法--以Java程序设计为例》
<程序设计教学法--以Java程序设计为例> 当老师上的第一门课就是<Java程序设计>,工作以来,断断续续上了近十次课了吧.十几年来,教材.课程内容.教学方法.教学手段不断改 ...
- 20145206《Java程序设计》实验三实验报告
20145206<Java程序设计>实验三实验报告 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运 ...
- Java程序设计 实验三
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1353 姓名:李海空 学号:20135329 成绩: 指 ...
- 20145320 《Java程序设计》第2周学习总结
20145320 <Java程序设计>第2周学习总结 教材学习内容总结 3.1 类型.变量与运算符 基本类型 整数(short.int.long) .字节(byte) .浮点数(float ...
- 《Java程序设计》课程准备之问卷调查
一.你对自己的未来有什么规划?做了哪些准备? 答:未来就是找个好工作,在保证自己与父母生活条件良好的基础上,进一步的提高精神上的需求.如:旅游度假,支持更多业余爱好等.准备就是:好好学习,好好运动,好 ...
- 20155324 《Java程序设计》实验三 敏捷开发与XP实践
20155324 <Java程序设计>实验三 敏捷开发与XP实践 实验内容 XP基础 1.XP核心实践 2.相关工具 实验步骤 敏捷开发与XP 1.敏捷开发(Agile Developme ...
- 20155328 2016-2017-2 《Java程序设计》第九周学习总结
20155328 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 16.1 JDBC入门 JDBC是Java联机数据库的标准规范,定义一组标准类与接口,应用程 ...
随机推荐
- APP开通支付宝支付 转账功能
注意:支付宝单笔转账到账户功能的准入条件 首先要在商家中心注册,从商家中心可以跳转到开放平台. 登陆蚂蚁金服开放平台 1 开发中心->网页&移动应用 2 根据需求选择应用类型创建应用 3 ...
- AWS、阿里云、Azure、Google Cloud、华为云、腾讯云 各种云服务器价格收费对比(上)
他来了,他来了~ 他带着六家公有云厂商的资源价格走来了~ 不久前,我们上线了一款小工具——[多云成本计算器]1.0版,公众号菜单栏可以直接体验.详细介绍可以戳这里<3秒即得最低价,速石上线「多云 ...
- 【LC_Lesson1】--字符串反转练习
LeetCode算法练习题目一: 给定一个字符串,要求将该字符串反转后输出 努力学习,天天向上.借助LeetCode的题目,练习编码能力,数据结构,以及C++和Python的编码能力. 一. 算法实现 ...
- 枚举 + exgcd
题意:已知xi=(a*xi-1+b) mod 10001,且告诉你x1,x3.........x2*t-1,让你求出其偶数列 思路分析 : 题目所要求的的是对 10001 取余,由模运算的性质可知,a ...
- electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint
我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...
- Xmind: ZEN快捷键
- ASP.NET 开源导入导出库Magicodes.IE 导出Pdf教程
基础教程之导出Pdf收据 说明 本教程主要说明如何使用Magicodes.IE.Pdf完成Pdf收据导出 要点 导出PDF数据 自定义PDF模板 导出单据 如何批量导出单据 导出特性 PdfExpor ...
- form get
<form action=""> <input type="text" name="query" id="&qu ...
- [bzoj4524] [loj#2047] [Cqoi2016] 伪光滑数
Description 若一个大于 \(1\) 的整数 \(M\) 的质因数分解有 \(k\) 项,其最大的质因子为 \(Ak\) ,并且满足 \(Ak^K \leq N\) , \(Ak<12 ...
- [洛谷P4585] [FJOI2015] 火星商店问题
Description 火星上的一条商业街里按照商店的编号 \(1\),\(2\) ,-,\(n\) ,依次排列着 \(n\) 个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数 \(va ...