编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

Java设计模式的7种设计原则还有部分人不知道

gowuye 2024-04-03 16:15 20 浏览 0 评论

前言

其实没有设计模式我们也能完成开发工作。但是为什么需要设计模式呢?让你看起来很牛,没错这个算一个。让你的代码层次感分明,可读性强而且容易维护。让你像我一样有更多的摸鱼划水时间。

可能有人说我一个类或者方法就干完的东西,你搞了七八个。当然使用设计模式也是要斟酌的。一些简单稳定的业务也不推荐使用设计模式。设计模式多用于复杂多变的业务或者要求适配性、扩展性更强的场景中。不要为了设计模式而设计模式。

接下来我们结合实际开探讨一下Java设计模式的一些原则。

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、合成/复用原则

它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。

总结

这七种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中,开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。在实际开发中我们可以根据业务来进行设计模式的使用,但是很重要的一点千万不要被这些条条框框束缚了你的手脚。

最后

欢迎大家一起交流,喜欢文章记得关注我点赞转发哟,感谢支持!

相关推荐

嵌入式C语言中常量的应用实例(嵌入式c语言中常量的应用实例是什么)

常量,我们都知道,就是数值保持不变的量。在C语言中,常量一旦初始化了,它的值将在整个程序运行周期内,不允许发生任何变化。常量与变量是相对的,我们实际项目中经常会用到它。定义常量的两种方式C语言中主要有...

C语言编程基础知识汇总学习,适合初学者!更新常量知识

(二)整型常量整型常量有3种形式:十进制整型常量、八进制整型常量和十六进制整型常量。(注意:c语言中没有直接表示二进制的整型常量,在c语言源程序中不会出现二进制。)书写方式如下:十进制整型常量:123...

【C语言】第二章第六节:字符串常量

第二章第六节:字符串常量。下表C语言中的常用转义字符。·字符形式功能:ASCIl码(十进制形式)。→\t水平制表(横向跳格:跳到下一个tab位置)。→\b退格8。→\r回车(不换行,光标移到本行行首)...

「GCTT 出品」Go 系列教程——5. 常量

这是我们Golang系列教程的第五篇。定义在Go语言中,术语”常量”用于表示固定的值。比如5、-89、IloveGo、67.89等等。看看下面的代码:varaint=50v...

每日C语言-常量指针、指针常量、指向常量的指针常量

一、常量指针1)什么是常量指针?通过该指针不可以修改其所指向存储单元中的值指针本身即地址可以被修改2)定义:类型说明符const*指针变量;类型说明符表示指针所指向存储单元中的值得数据类型指针...

C语言-符号常量、常变量、变量之我见

更新内容:新增音频。音频和文章一起更配oHello,大家好,又和大家见面了~~相信很多朋友们听了C语言的“符号常量”、“常变量”、“变量”后还是对这三者一脸懵逼吧。不管老师怎么歇斯底里地讲解,同学们迷...

零基础带你学习C语言:四:探索常量与变量

前言常量与变量学习;一:分析:short、float、long类型#include<stdio.h>intmain(){shortage=18;floatweight=12...

C语言中是如何定义常量的?那定义字符串呢?

常量有整型常量、浮点型常量、字符型常量及字符串常量。‘常量定义是指定义符号常量,用一个标识符来代表一个常量,通过宏定义预处理指令来实现。常量的定义:#definecount60这就定义了一个常量...

C语言符号常量的优点,会是那几点?

符号常量是一个常量,是不变量,所以,在编译的时候,就把符号常量出现的地方,替换为符号常量对应的常量。符号常量一般用户定义一个全局使用的数据,而且要改变该数据的时候,只需要改变符号常量的值,代码中引用符...

嵌入式开发- C语言数据类型-常量(c语言嵌入式是干嘛的)

基本数据类型的常量-掌握**整型常量:**常量是指在程序运行期间其数值不发生变化的数据。整型常量通常简称为整数整数可以是十进制数、八进制数、十六进制数八进制06334十六进制0xd1...

c语言解剖课:只读变量、常量、字面量傻傻分不清?

写在前面本篇主题的缘起,是因为一个计算机专业的大学生在和我讨论c语言问题时,说const常量如何如何,我说变量被const修饰了,还是变量,不是“常量”。他给了我一个截图:他说大模型都是这样回答的,变...

C/C++编程笔记:C数组、字符串常量和指针!三分钟弄懂它

想弄懂C语言中数组和指针的关系吗?这篇文章就占据你三分钟时间,看完你肯定会有收获!数组数组声明为数据类型名称[constant-size],并将一个数据类型的一个或多个实例分组到一个可寻址的位...

C语言入门到精通【第008讲】——C语言常量

C语言常量常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。常量就像是常规的变量,只不过常...

这是C语言无法修改得东西,C语言基础教程之常量解析

常量是指程序在执行期间不会改变的固定值。这些固定值也称为文字。常量可以是任何基本数据类型,如整数常量,浮点常量,字符常量或字符串文字,还有枚举常量。常量被视为常规变量,除了它们的值在定义后无法修改。整...

C语言中的单精度、双精度、常量等都有什么意思?

刚接触C语言时,对于常量,变量,浮点,单精度,双精度等问题的理解,大都很模糊不清,其实在程序运行过程中,其值不能改变的量称为常量。如12、0、-3为整型常量,4.6、-1.23为实型常量,'a'、'...

取消回复欢迎 发表评论: