欢迎来到开启编程思想之旅,进入小刘脑壳了

6大设计原则

第1章 单一职责原则(专一才会强 )

那问题就来了我们应该如何实现这一原则呢

思考问题的时候多以,第一人称视角来看,我写着这个接口,或者抽象类的作用是什么。

举个简单点的生活栗子,

小明去开奔驰车。

来构建

小明 :人的一种 ----> 抽象 Abstract Person (功能就是完成把小明这个人给创造出来)

小明有会驾驶的功能---->抽象 interface IDriver(功能就是会开车)

奔驰车是车的一种---->抽象 Abstract ICar(功能就是造汽车)

 

上面就是单一职责,谁也不牵扯谁,小明是有一个人,会不会开车无所谓,和有没有奔驰车更无所谓了

我的理解

为啥得这样说呢,单一的设计原则,

1,我们就可以好的编写代码,功能简单,容易完成,而且

当我们想要改变的时候就特别轻松,而且它们不会相互干涉。

2,业务逻辑简洁的多,我们要完成一个功能我们就调用它的接口就可以了,不用考虑细节是怎么实现的,脑子就不会太混乱了, 想的就不会太多了。

3.在编程的世界里面,每个类都有自己的功能和职责,只有完成了自己的职责才可以更好的服务其他人,不要越界和干扰其他人滴

类和方法也尽量使用这种原则,一个类和一个方法只是完成一个功能。

 

 

如何去划分是否是一个功能呢

 

 

2d23873236e440599e94245e66515265.png

 

 

 

按照职责划分(不同的功能就有不容的职责)

e01140e7ba2e43c5bb120013dfbdc681.png

 

只有一个因素导致类的不同,不同的接口可以别不同类的实现,着一个类表示了一个具体的实现的功能

IUserInfo userInfo = new UserInfo();
//我要赋值了,我就认为它是一个纯粹的BO
IUserBO userBO = (IUserBO)userInfo;
userBO.setPassword("abc");
//我要执行动作了,我就认为是一个业务逻辑类
IUserBiz userBiz = (IUserBiz)userInfo;
userBiz.deleteUser();

接口单一职责,但是类尽量做到只有这一个原因(一个功能)而导致的类的不同。

好处:1,代码功能更简洁便于实现,

2.易于修改和维护

3.可读性提高

 

第2章 里氏替换原则(子扩展于父,子可以替换父)

我的理解

父类创造子类继承,子类去创造改写父类,父类出现的地方子类当然能出现。

父类的范围肯定是大于子类的范围的,父类范围是默认的,子类 可以是是protect或者是private但是绝对不能是public的

更像是Java中的继承概念

继承的好处

  1. 代码共享,减少创建类的工作量

  2. 提高代码的重用性;

  3. 子类可以形似父类,但又异于父类,(扩充自己的东西)

  4. 提高代码的可扩展性,实现父类的方法就可以“为所欲为”了

  5. 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;

特带:

1,子类继承了父类就有了父类的属性和方法,

2,只要父类能出现的地方子类就可以出现,而且 替换为子类也不会产生任何错误或异常,但是有子类出现的地方,父类未必就能适应(因为子类是有自己的东西的,父类不一定能够适应)

要满足继承的四个要求

1.子类必须完全实现父类的方法

 

1032d4f6deab4294be5d68327972deb2.png

 

注意:在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明 类的设计已经违背了LSP原则。

2.子类可以有自己的个性

 

5c6218fc76b647259fb8dc3a75414ee4.png

 

3.子类覆盖或实现父类的方法时输入参数可以被放大

代码清单2-11 Father类源代码
public class Father {
public Collection doSomething(HashMap map){
System.out.println("父类被执行...");
return map.values();
}
}
这个类非常简单,就是把HashMap转换为Collection集合类型,然后再定义一个子类,源
代码如代码清单2-12所示。
代码清单2-12 子类源代码
public class Son extends Father {
//放大输入参数类型
public Collection doSomething(Map map){
System.out.println("子类被执行...");
return map.values();
}
}
​
  1. 覆写或实现父类的方法时输出结果可以被缩小

,父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆 写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一 个类型,要么S是T的子类.

因为这样的话,子类才可以出现到父类情况,父类的类型高,可以接受子类的

第3章 依赖倒置原则(人的思维决定程序,抽象相互作用,细节实现)

我的理解:

发生作用的是脑子里面出现的,不是具体的,是抽象的,我们是现在脑子里面把现实生活中的一系列的具体的事务抽象出来,然后在具体的做它。

举个简单的例子

小明去看电影

小明想在几点到那个电影院去看电影。

这都是不确定定,假设,张三要到A电影院看小猪佩奇,李四到B电影院看功夫熊猫,是不是太乱了

没关系,我们换一种思维我们并不关心谁,谁去看电影,在那个电影院,看什么电影,因为这种太多太多了,无法确定的,抽象点哥们,它们之间发生关系的就是人去电影院看电影。

抽象出来,人 ,电影院 ,看电影

无论是是谁他总是个人吧, A电影院也是 电影院, 恐怖电影也是电影的一种。

到了我们具体去看电影的时候再去实现它的细节,比如张三,功夫熊猫电影,A电影院(并不发生关系,抽象的我们已经写过了)

在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实 现类,实现接口或继承抽象类而产生的类就是细节。

 

● 高层模块不应该依赖低层模块,两者都应该依赖其抽象;

解释:每一个逻辑的实现都是由原子逻辑组成的,不可分割的 原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。

 

模块之间的依赖是通过抽象的产生的(模块之间的业务逻辑是通过抽象或者接口来完成的)

● 抽象不应该依赖细节;

在抽象的类或者接口里面不要出现具体的类(就是别出现不是接口和抽象类的, 属性也是的)

注意:我们尽量不要重写父类的方法,尽管这很方便,但是业务逻辑可能发生变化,是父类抽象类或者接口来具体实现的。

● 细节应该依赖抽象。

每个具体的实现类尽量都有自己的接口或者是抽象类

注意在Java中定义变量的时候要注意的问题,只要定义变量的话,就有两个类型,一种是表面类型(抽象类型或者接口类型,并不是真正创建内存空间的), 一种是实际类型(对象的类型,new 类型)。尽量保证表面类型是定义变量,具体实现使用实际变量

“面向接口编程”——OOD(Object-Oriented Design,面向对象设 计)的精髓之一

 

我理解的依赖倒置原则,就是,倒置是关系的倒置, 抽象在脑子里面的才是我们所使用的,具体业务逻辑都是发生在脑子里面的,完成的操作肯定就是抽象类或者是接口嘞

这样程序的可扩展性就大幅度提升了。

java 的三种依赖的写法

1.构造函数传递依赖对象

public interface IDriver {
//是司机就应该会驾驶汽车
public void drive();
}
public class Driver implements IDriver{
private ICar car;
//构造函数注入
public Driver(ICar _car){
this.car = _car;
}
//司机的主要职责就是驾驶汽车
public void drive(){
this.car.run();
}
}

2.Setter方法传递依赖对象

public interface IDriver {
//车辆型号
public void setCar(ICar car);
//是司机就应该会驾驶汽车
public void drive();
}
public class Driver implements IDriver{
private ICar car;
public void setCar(ICar car){
this.car = car;
}
//司机的主要职责就是驾驶汽车
public void drive(){
this.car.run();
}
}

3.接口声明依赖对象

85df136068a149708f9144dd5388e423.png

 

建立两个接口:IDriver和ICar,分别定义了司机和汽车的各个职能,司机就是驾驶汽 车,必须实现drive()方法

public interface IDriver {
//是司机就应该会驾驶汽车
public void drive(ICar car);
}
​

接口只是一个抽象化的概念,是对一类事物的最抽象描述,具体的实现代码由相应的实 现类来完成,Driver实现类

public class Driver implements IDriver{
//司机的主要职责就是驾驶汽车
public void drive(ICar car){
car.run();
}
}

在IDriver中,通过传入ICar接口实现了抽象之间的依赖关系,Driver实现类也传入了ICar 接口,至于到底是哪个型号的Car,需要在高层模块中声明。

ICar及其两个实现类的实现

public interface ICar {
//是汽车就应该能跑
public void run();
}
public class Benz implements ICar{
//汽车肯定会跑
public void run(){
System.out.println("奔驰汽车开始运行...");
}
}
public class BMW implements ICar{
//宝马车当然也可以开动了
public void run(){
System.out.println("宝马汽车开始运行...");
}
}
​

在业务场景中,我们贯彻“抽象不应该依赖细节”,也就是我们认为抽象(ICar接口)不 依赖BMW和Benz两个实现类(细节),因此在高层次的模块中应用都是抽象

public class Client {
public static void main(String[] args) {
IDriver zhangSan = new Driver();
ICar benz = new Benz();
//张三开奔驰车
zhangSan.drive(benz);
}
}
​

IDriver,Benz的表面类型是ICar,也许你要问,在这个高层模块中也调用到了低层模块,比 如new Driver()和new Benz()等,如何解释?确实如此,zhangSan的表面类型是IDriver,是一 个接口,是抽象的、非实体化的,在其后的所有操作中,zhangSan都是以IDriver类型进行操 作,屏蔽了细节对抽象的影响

为啥这样说呢

张三如果要开宝马车,也很容易,我们只要修改业务 场景类就可以,实现过程如代码清单所示。

public class Client {
public static void main(String[] args) {
IDriver zhangSan = new Driver();
ICar bmw = new BMW();
//张三开奔驰车
zhangSan.drive(bmw);
}
}

在新增加低层模块时,只修改了业务场景类,也就是高层模块,对其他低层模块如 Driver类不需要做任何修改,业务就可以运行,把“变更”引起的风险扩散降到最低。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗中的代码猿--刘同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值