软件设计原则

1.开闭原则

官方解释:对扩展开放,对修改关闭。 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。

简而言之:使用接口和抽象类, 当需要对模块进行扩展的时候,只需要新增一些实现类就能实现。

分析: 我现在有个动物叫声的接口:AnimalCalls ,现在我这个模块有猫的叫声和狗的叫声。

而现在,我想要向这个模块中加入兔子的叫声,我只需要新加一个实体类 Rabbit 去继承 AnimalCalls 并重写一下 call() 就可实现,只是在 AnimalCallscall() 上去进行了扩展,并没有改写 call() 的内容(因为它是一个抽象方法,没有内容)。

2.里氏代换原则

官方解释:任何基类可以出现的地方,子类一定可以出现。

简而言之:子类可以扩展父类的功能,但不能改变父类原有的功能。 就是子类尽量别去重写父类的方法,这样就能保证:父类使用的地方,子类也能使用,因为子类只是在父类的基础上新增了功能,所有子类可以使用父类的所有功能。而为了实现这种效果,就是让子类实现接口

分析: 经典案例 List<T> list = new ArrayList<>();Map<T> map = new HashMap<>();,打开源码或者查看API文档就能体会到了,这里就不做过多解释了

3.依赖倒转原则

官方解释:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

这里,来对上面提到的几个名词做一下解释:

  • 抽象——接口/抽象类。
  • 细节——实现类。

简而言之:对抽象进行编程,而不是对实现进行编程, 降低客户与实现模块之间的耦合度。

分析: 现在我要组装一件商品,他需要两种零件(A和B),而这两种零件分别有两种品牌(GuA、CastB)。那么直接用实现类实现就是这样的:

而现在,又有一种新的品牌(ByteA)进入市场,它比起GuA有着更低的售价,所以我决定要替换掉GuA,那么我首先得和GuA断绝联系,再使用ByteA,如下:

这样就显得过程很繁琐。

那来看一下使用接口的方案:

这样,就能很轻松地根据市场行情切换我想要使用的零件品牌

4.接口隔离原则

官方解释:不应强迫客户端依赖它不使用的方法。

简而言之:使接口的行为单一, 也就是一个接口只专注于一个功能(一个方法,或者没有方法)。

分析: 经典案例:

  • java.io.Serializable 这个接口啥方法都没有,它的作用就是证明实现它的实体类可以进行序列化
  • java.lang.Comparable 这个接口就只有一个方法compareTo,只专注于实体类的排序
  • java.lang.Cloneable 这个接口没有方法,它的作用就是声明实现类可以调用Object.clone()对实体类的实例进行克隆

好了,看完这三个经典案例,想必大家就已经了然于心了

5.迪米特法则

官方解释:一个类对于其他类知道的越少越好, 一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。

这里,来对上面提到的几个名词做一下解释:

  • 朋友:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

简而言之: 一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。其目的是降低类之间的耦合度,提高模块的相对独立性。

分析: 房主把房子交给中介,让中介与租户联系实现房屋出租就能很好解释这个法则:



上述案例的具体实现可观看我的博客:代理模式(静态代理、jdk动态代理、CGLib动态代理),好的,这一段就到这里吧

6.合成复用原则

官方解释:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

简而言之: 继承具有很多缺点,建议使用组合或聚合。

  • 继承的缺点:
    • 破坏了类的封装性:因为继承会将父类的实现细节暴露给子类,父类对子类是透明的
    • 父子耦合度高:父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护
    • 限制了复用的灵活性:从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化
  • 组合或聚合的优点:
    • 维持了类的封装性:因为成分对象的内部细节是新对象看不见的
    • 对象间的耦合度低:可以在类的成员位置声明抽象
    • 复用的灵活性高:这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象

分析:

  • 汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“颜色”划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就很多。类图如下:

从上面类图我们可以看到使用继承复用产生了很多子类,如果现在又有新的动力源或者新的颜色的话,就需要再定义新的类。我们试着将继承复用改为聚合复用看一下:

上述案例的具体实现代码可以去看这篇文章:设计原则之合成复用原则,这里我就懒得写了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

364.99°

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

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

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

打赏作者

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

抵扣说明:

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

余额充值