我是靠谱客的博主 笨笨水壶,最近开发中收集的这篇文章主要介绍设计模式7大原则——开闭&单一职责&里氏替换,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原则一:开闭原则(总纲和核心)

开闭原则规定软件中的对象(类、模块、函数等)对扩展开放,对修改封闭。也就是说针对需求的修改,我们要用扩展来实现,而不是通过修改已有代码来实现。

为了方便大家理解,我用王者荣耀来举例,王者荣耀中这么多英雄,如果把所有英雄都集中在一个类中来实现那是不现实的。你想想每次增加新英雄或者修改英雄的属性都要修改这一个类,那程序员还不疯了!时间长了,里面的逻辑之复杂,功能之紊乱真会要人命的。因此英雄联盟每次增加新英雄都会扩展增加一个新英雄类,这个新英雄类当然是继承“抽象英雄类”,然后实现里面的方法来定制自己的属性和功能。这就是对扩展开放,而修改关闭。

优点

(1).方便测试。我们只能以新增加的类进行测试,而不需要管其他的类。

(2).提高复用性。我们把功能拆分成一个一个小功能,是方便我们重复使用的。

(3).提高可维护性。想一下:如果有需求增加或者修改,你是希望重新扩展个类重新写呢?还是阅读别人的代码修改逻辑?

(4).符合面向对象的开发要求。

原则二:单一职责原则

“不要让类太累!”。单一职责原则规定一个类只有一个职责。如果有多个职责(功能)被设计在一个类中,这个类就违反了单一职责原则。其实这不难理解,生活中我们也是这样:专门人做专业事,即使放到公司和国家中也是这样。都会分好几个部门来处理不同的事情,不可能一个部门处理公司所有事情。

优点

(1).类的复杂性降低了,各个类都有明确清晰的职责。

(2).类的可读性提高了,我就见过这么一个同事,把好多的逻辑处理都放在一个方法中完成,看着那好几百行的方法,我真想打死他。

(3).可维护性提高了,类的功能简单了,可读性高了,自然可维护性就提高了。

虽然理论说起来简单,但是和业务结合起来这个就不是太容易了,所以要结合业务来权衡,对于这个原则,我建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

原则三:里氏替换原则

这个原则比较难理解,下面我会花费很大篇幅来讲解这个原则。

里氏替换原则是针对继承中出现的问题进行规范,它要求:任何基类可以出现的地方,子类一定可以出现。通俗点讲:子类可以扩展父类的功能,可以实现父类抽象方法,但不能改变父类原有的功能或者非抽象方法。

子类可以扩展父类的功能我们可以理解,就是说子类可以添加父类没有的功能。但是子类不能改变父类原有的功能能或者非抽象方法如何理解呢?

我们先想想加入子类更改的父类原有的功能会出现什么问题。我们举例说明:

假设长方形类:

public class Rectangle{
    setWidth(int width){
        this.width=width;
    }
    setHeight(int height){
        this.height=height
    }
}

我们知道,正方形属于长方形,所以正方形应该继承长方形,注意继承的时候:正方形不能更改父类原有的功能,如果改了,那正方形就不再属于长方形了。因为它违背了:任何基类可以出现的地方,子类一定可以出现。

正方形类:

public class Square extends Rectangle{
  	setWidth(int width){
      this.width=width;
      this. height=width;
    }
  setHeight(int height){
    this.setWidth(height);
  }
}

这个正方形已经将继承来的setWidth方法和setHeight方法更改了,这就坏了,我们来使用一下你就看明白了。

//重新设置尺寸
public void resize(Rectangle r){
    if(r.getHeight()<=r.getWidth){
   				 r.setHeight(r.getWidth+1);
    }
}

看的出当我们重新设置尺寸的时候,把Rectangle 的对象传进去 和 Square 传进去,运行的效果是不一致的,这也就违背了“任何基类可以出现的地方,子类一定可以出现”的原则。

相信说到这里大家能明白了吧。

具体在使用这个原则的时候有以下几点要求:

  • 子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。

  • 子类中可以增加自己特有的方法。

  • 当子类覆盖或实现父类的方法时,方法形参要比父类方法的形参更宽松。

  • 当子类的方法实现父类的抽象方法时,方法的返回值要比父类更严格。

下面我着重来讲解一下第三条:当子类覆盖或实现父类的方法时,方法形参要比父类方法的形参更宽松。

父类一个方法func(HashMap map); 子类方法func(Map map);

父类实例fu,子类实例zi,里氏替换原则要求fu.func(HashMap或子类) 必须和zi.func(HashMap或子类) 调用的是同一方法,试想如果子类方法func参数范围比父类的窄的话,zi.func就会优先调用子类的方法,这样就违背了里氏替换原则的基本定义了。

第四条也是同样的道理,如果子类方法的返回值要比父类更宽松的话,那么会优先调用子类的方法,这样也就违背了里氏替换原则的基本定义了。

好了,就先分享到这里,关注我,java学习不头秃,还为每位粉丝准备了一份全面的资料福利,从面试简历模板大厂面经汇总,从大厂内部技术资料互联网高薪必读书单,以及Java面试核心知识点(283页)Java面试题合集2022年最新版(485页)等等,有需要的可以点下方名片领取

最后

以上就是笨笨水壶为你收集整理的设计模式7大原则——开闭&单一职责&里氏替换的全部内容,希望文章能够帮你解决设计模式7大原则——开闭&单一职责&里氏替换所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部