代码规范七大原则_设计模式的七大原则详解||上篇
Hello 丨World
当机会变得稀有,当竞争变得激烈
当方向不再清晰,当风口不再有风
关键词||设计模式
全文约7685字,细读大约需要20分钟
1 认识设计模式
1.1 什么是设计模式
所谓设计模式,就是对经常出现的软件设计问题的成熟解决方案。
很多人把设计模式想象成非常高深的概念,实际上设计模式仅仅是对特定问题的一种惯性思维。一些人喜欢抱着一本设计模式的书研究,以期成为一个“高手”,实际上设计模式的理解必须以足够的代码积累量作为基础,最好是经历过某种痛苦,或者正在经历一种苦痛,就会对设计模式有较深的感受。
1.2 设计模式的目的
编写软件的过程中,程序员面临着来自耦合性、内聚性以及可维护性、可扩展性、重用性、灵活性等多方面的挑战,设计模式是为了让程序拥有更好的:
代码可重用性。相同功能的代码,不用多次编写;
可读性。便于其他程序员的阅读和理解;
可扩展性。当需要增加新功能时,非常方便;
可靠性。当增加新的功能后,对原来的功能没有影响;
使程序呈现高内聚、低耦合的特点。
1.3 什么是设计模式的原则?
设计模式原则,其实就是程序员在编程时,应当遵循的原则,也就是各种设计模式的基础,即设计模式为什么这样设计的依据。
设计模式的七大原则有:
单一职责原则
接口隔离原则
依赖倒置原则
里氏替换原则
开闭原则
迪米特法则
合成复用原则
2 单一职责原则
2.1 什么是单一职责原则
对类来说,一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2,当职责1需求变更而改变类A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2。
2.2 应用实例
方案一:
1/** 2 * 方式一的run方法中,违反了单一职责原则, 3 * 解决的方案是根据交通工具运行方法不同,分解成不同类即可 4 */ 5 6public class SingleResponsebility1 { 7 8 public static void main(String[] args) { 910 Vehicle vehicle = new Vehicle();1112 vehicle.run("汽车");1314 vehicle.run("摩托");1516 vehicle.run("飞机");1718 }1920}2122class Vehicle {2324 public void run(String vehicle) {2526 System.out.println(vehicle+"在公路上跑");27 }28}
方案二:
1/** 2 3 * 方案二遵循单一职责原则 4 5 * 但是这样做的改动很大,即将类分解,同时修改客户端 6 7 * 改进:直接修改Vehicle类,改动的代码会比较少 8 9 */1011public class SingleResponsibility2 {1213 public static void main(String[] args) {1415 Vehicle1 vehicle1 = new Vehicle1();1617 vehicle1.run("汽车");1819 Vehicle2 vehicle2 = new Vehicle2();2021 vehicle2.run("轮船");2223 Vehicle3 vehicle3 = new Vehicle3();2425 vehicle3.run("飞机");26 }2728}2930class Vehicle1{3132 public void run(String vehicle){3334 System.out.println(vehicle+"在地上跑");35 }36}3738class Vehicle2{3940 public void run(String vehicle){4142 System.out.println(vehicle+"在水上跑");43 }4445}4647class Vehicle3{4849 public void run(String vehicle){5051 System.out.println(vehicle+"在天上跑");5253 }5455}
方案三:
1/** 2 * 这种修改方法没有对原来的类做大的修改,只是增加方法 3 * 这里虽然没有在类这个级别上遵循单一职责原则,但是在方法级别上,仍然遵守这个原则 4 */ 5 6public class SingleResonsibility3 { 7 8 public static void main(String[] args) { 910 Vehicle4 vehicle4 = new Vehicle4();1112 vehicle4.run("汽车");1314 vehicle4.run2("轮船");1516 vehicle4.run3("飞机");17 }1819}2021class Vehicle4{2223 public void run(String vehicle){2425 System.out.println(vehicle+"在地上跑");2627 }2829 public void run2(String vehicle){3031 System.out.println(vehicle+"在水上跑");3233 }3435 public void run3(String vehicle) {3637 System.out.println(vehicle + "在天上跑");38 }39}
2.3 注意事项
降低类的复杂度,一个类只负责一项职责;
提高类的可读性、可维护性;
降低变更引起的风险;
通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则:只有类中方法数量足够少,可以在方法级别保存单一职责原则。
3 接口隔离原则
3.1 什么是接口隔离原则
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
3.2 应用实例
如图,类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类D,如果接口Interface1对于类A和类C来说不是最小接口,那么类B和类D必须去实现他们不需要的方法。
1public class Segregation1 { 2 3} 4 5//接口 6interface Interface1 { 7 8 void operation1(); 9 10 void operation2(); 11 12 void operation3(); 13 14 void operation4(); 15 16 void operation5(); 17 18} 19 20class B implements Interface1 { 21 22 @Override 23 24 public void operation1() { 25 26 System.out.println("B实现了operation1"); 27 } 28 29 @Override 30 31 public void operation2() { 32 33 System.out.println("B实现了operation2"); 34 } 35 36 @Override 37 38 public void operation3() { 39 40 System.out.println("B实现了operation3"); 41 42 } 43 44 @Override 45 46 public void operation4() { 47 48 System.out.println("B实现了operation4"); 49 } 50 51 @Override 52 53 public void operation5() { 54 55 System.out.println("B实现了operation5"); 56 } 57 58} 59 60class D implements Interface1 { 61 62 @Override 63 64 public void operation1() { 65 66 System.out.println("D实现了operation1"); 67 68 } 69 70 @Override 71 72 public void operation2() { 73 74 System.out.println("D实现了operation2"); 75 76 } 77 78 @Override 79 80 public void operation3() { 81 82 System.out.println("D实现了operation3"); 83 84 } 85 86 @Override 87 88 public void operation4() { 89 90 System.out.println("D实现了operation4"); 91 } 92 93 @Override 94 95 public void operation5() { 96 97 System.out.println("D实现了operation5"); 98 99 }100101}102103class A {104105 public void depend1(Interface1 i) {106107 i.operation1();108 }109110 public void depend2(Interface1 i) {111112 i.operation2();113114 }115116 public void depend3(Interface1 i) {117118 i.operation3();119120 }121122}123124class C {125126 public void depend1(Interface1 i) {127128 i.operation1();129130 }131132 public void depend4(Interface1 i) {133134 i.operation4();135136 }137138 public void depend5(Interface1 i) {139140 i.operation5();141 }142}
按隔离原则应当这样处理:将接口Interface1拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。
1public class Segregation2 { 2 3 public static void main(String[] args) { 4 5 A a = new A(); 6 7 a.depend1(new B()); 8 9 a.depend2(new B()); 10 11 a.depend3(new B()); 12 13 C c = new C(); 14 15 c.depend1(new D()); 16 17 c.depend4(new D()); 18 19 c.depend5(new D()); 20 21 } 22 23} 24 25//接口 26interface Interface1 { 27 28 void operation1(); 29 30} 31 32interface Interface2 { 33 34 void operation2(); 35 36 void operation3(); 37 38} 39 40interface Interface3 { 41 42 void operation4(); 43 44 void operation5(); 45 46} 47 48class B implements Interface1, Interface2 { 49 50 @Override 51 52 public void operation1() { 53 54 System.out.println("B实现了operation1"); 55 56 } 57 58 @Override 59 60 public void operation2() { 61 62 System.out.println("B实现了operation2"); 63 64 } 65 66 @Override 67 68 public void operation3() { 69 70 System.out.println("B实现了operation3"); 71 72 } 73 74} 75 76class D implements Interface1, Interface3 { 77 78 @Override 79 80 public void operation1() { 81 82 System.out.println("D实现了operation1"); 83 84 } 85 86 @Override 87 88 public void operation4() { 89 90 System.out.println("D实现了operation4"); 91 92 } 93 94 @Override 95 96 public void operation5() { 97 98 System.out.println("D实现了operation5"); 99100 }101102}103104class A {105106 public void depend1(Interface1 i) {107108 i.operation1();109110 }111112 public void depend2(Interface2 i) {113114 i.operation2();115116 }117118 public void depend3(Interface2 i) {119120 i.operation3();121122 }123124}125126class C {127128 public void depend1(Interface1 i) {129130 i.operation1();131132 }133134 public void depend4(Interface3 i) {135136 i.operation4();137138 }139140 public void depend5(Interface3 i) {141142 i.operation5();143144 }145146}
4 依赖倒转原则
4.1 什么是依赖倒转原则
依赖倒转原则是指高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;依赖倒转的中心思想是面向接口编程。
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或者抽象类,细节就是具体的实现类。
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
4.2 应用实例
请编程完成persion接收消息的功能。
方案一:
1public class DependecyInversion { 2 3 public static void main(String[] args) { 4 5 Persion persion = new Persion(); 6 7 persion.receive(new Email()); 8 } 9}1011class Email {1213 public String getInfo() {1415 return "电子邮件:Hello World!!!";16 }17}1819class Persion {2021 public void receive(Email e) {2223 System.out.println(e.getInfo());24 }25}
方案二:
1/** 2 3 * 如果我们获取的对象是微信、短信等等,则新增类,同时Persion也要增加相应的接收方法 4 5 * 解决思路:引入一个抽象的接口IReceiver,表示接收者,这样Persion类与接口IReceiver发生依赖 6 7 * 因为Email、WeChat等等属于接收的范围,它们各自实现IReceiver接口就可以,这样我们就符合依赖倒转原则 8 9 */1011public class DependecyInversion2 {1213 public static void main(String[] args) {1415 Persion2 persion2 = new Persion2();1617 persion2.receive(new Email2());1819 persion2.receive(new WeChat());20 }21}2223interface IReceiver {2425 public String getInfo();26}2728class Email2 implements IReceiver {2930 @Override31 public String getInfo() {3233 return "电子邮件:Hello World!";34 }35}3637class WeChat implements IReceiver {3839 @Override40 public String getInfo() {4142 return "微信消息:Hello weixin";43 }44}4546class Persion2 {4748 public void receive(IReceiver i) {4950 System.out.println(i.getInfo());51 }52}
4.3 依赖传递的三种方式
接口传递、构造方法传递、setter方法传递。
1//第一种方式:接口传递 2//开关的接口 3interface IOpenAndClose { 4 5 public void opoen(ITV tv);//抽象方法,接收接口 6} 7 8interface ITV {//ITV接口 9 public void play();10}1112//实现接口13class OpenAndColse implements IOpenAndClose {1415 @Override16 public void opoen(ITV tv) {1718 tv.play();19 }20}
1//方式二:构造方法传递 2interface IOpenAndClose { 3 4 public void open();//抽象方法 5} 6 7interface ITV {//ITV接口 8 public void play(); 9}1011class OpenAndClose implements IOpenAndClose {1213 public ITV tv;//成员1415 public OpenAndClose(ITV tv) {//构造方法1617 this.tv = tv;18 }1920 @Override21 public void open() {2223 this.tv.play();24 }25}
1//方式三:setter方法传递 2interface IOpenAndClose { 3 4 public void open();//抽象方法 5} 6 7interface ITV {//ITV接口 8 9 public void play();10}1112class OpenAndClose implements IOpenAndClose {1314 private ITV tv;1516 public void setTv(ITV tv) {1718 this.tv = tv;19 }2021 @Override22 public void open() {2324 this.tv.play();25 }26}
4.4 注意事项
底层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好。
变量的声明类型尽量是抽象类或接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。
继承时要遵循里氏替换原则。
- END -
在电脑飞速发展的时代 丨我们不应该感到恐惧
因为我们可以跟电脑合作
成为一个人马合一、人枪合一、人电脑合一的新物种
这样的人才是这个时代的超级个体
代码规范七大原则_设计模式的七大原则详解||上篇相关推荐
- 接口隔离原则_设计模式之七大设计原则(上)
这是雷总20多年前写的汇编程序,像诗一样优雅 而中国诗词讲究平仄.押韵.对仗等一系列的规则原则, 那么想要写出像诗一样优雅的程序你不得不知的 -- 设计模式之七大原则: 1.开闭原则:对修改关闭,对扩 ...
- 设计模式六大原则_设计模式—设计六大原则
1. 单一职责原则(SRP) 定义:就一个类而言,应该仅有一个引起它变化的原因. 从这句定义我们很难理解它的含义,通俗讲就是我们不要让一个类承担过多的职责.如果一个类承担的职责过多,就等于把这些职责耦 ...
- java solid设计原则_设计模式之SOLID原则
什么是SOLID原则 SOLID = SRP(职责单一原则) + OCP(对扩展开发,修改关闭原则)+ LSP(里氏替换原则)+ ISP(接口隔离原则)+ DIP(依赖反转原则) SRP: Singl ...
- 依赖倒置原则_设计模式之SOLID原则
在程序设计领域, SOLID(单一功能.开闭原则.里氏替换.接口隔离以及依赖反转)是由罗伯特·C·马丁在21世纪早期引入,指代了面向对象编程和面向对象设计的五个基本原则.当这些原则被一起应用时,它们使 ...
- java 肌汉模式_设计模式之原型模式详解(附源代码)
原型模式(Prototype Pattern) 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. ...
- 数学建模_随机森林分类模型详解Python代码
数学建模_随机森林分类模型详解Python代码 随机森林需要调整的参数有: (1) 决策树的个数 (2) 特征属性的个数 (3) 递归次数(即决策树的深度)''' from numpy import ...
- 设计模式之模板方法模式详解
设计模式之模板方法模式详解 概述 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的 ...
- 设计模式之桥接模式详解
设计模式之桥接模式详解 文章目录 设计模式之桥接模式详解 一.什么是桥接模式 二.桥接模式的应用场景 三.桥接模式的角色组成 四.桥接模式通用写法示例 五.桥接模式优缺点 一.什么是桥接模式 桥接模式 ...
- 设计模式之策略模式详解
设计模式之策略模式详解 概述 先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车.可以坐汽车.可以坐火车.可以坐飞机. 作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有 ...
最新文章
- python自动发送微信公众号_使用python一步一步搭建微信公众平台(四)----将小黄鸡引入微信自动回复...
- 数字图像处理——第五章 图像复原
- python实现换位加密算法
- 高通qcc芯片天梯图_芯片性能天梯榜“爆冷”,骁龙888无法撼动麒麟9000的王位...
- 单例模式 代码以及祥解
- EMC测试仪器_智芯文库 | 单片机系统EMC测试和故障排除
- python聊天机器人
- 在业务控制方法中写入普通变量收集参数
- 快手通过标签添加好友_快手开通直播权限添加垂直标签
- BZOJ-4706 B君的多边形 OEIS
- Ubuntu录制gif动态图
- C语言全局变量和局部变量的区别详解
- 啊哈算法之水管工游戏
- 经验分享:兢兢业业工作5年的我不敌半年新人,原来“迪赛智慧数”才是升职加薪的关键!
- 分数阶 计算机应用,分数阶计算器
- SqlServer 汉字转换拼音首字母函数
- [转]Magento 2 and 1 Million Products
- 迁移学习的使用技巧和在不同数据集上的选择
- 06.破解Windows7密码
- 前端埋点设计/小程序+友盟埋点方案