2021年6月9日星期三

Java设计模式(4:里氏替换原则和合成复用原则详解

里氏替换原则最核心得一句话就是:子类可以扩展基类(父类)的功能,但不能改变父类原有的功能。 合成复用原则的核心是:复用时要尽量使用组合/聚合关系(关联关系),少用继承。

一、里氏替换原则

如果说实现开闭原则的关键步骤就是抽象化,那么基类(父类)和子类的继承关系就是抽象化的具体实现,所以里氏替换原则就是对实现抽象化的具体步骤的规范。即:子类可以扩展基类(父类)的功能,但不能改变父类原有的功能。

定义:一个软件实体如果适用一个父类的话,那一定是适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。

里氏替换原则最核心得一句话就是:子类可以扩展基类(父类)的功能,但不能改变父类原有的功能。它包含着四种含义:

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  2. 子类可以增持自己特有的方法。
  3. 当子类的方法重载父类的方法时,方法的前置条件(即:方法的参数)要比父类方法的输入参数更为宽松。
  4. 当子类的方法实现父类的方法时(重写/重载/实现抽象方法),方法的后置条件(即:返回值)要比父类更为更为严格或者相等。

我们先来做一个简单的计算器的功能,创建一个类SumA,实现一个两数相减的功能reduce()

public class SumA { // 相减 public int reduce(int a,int b){  return a - b; }}

再来创建一个类SumB,增加一个两数相加的功能,并且SumBSumA的子类:

public class SumB extends SumA { // 相加 public int reduce(int a,int b){  return a + b; }}

测试一下:

public static void main(String[] args) { SumB sumB = new SumB(); System.out.println("5 - 4 = "+sumB.reduce(5,4));}

结果:

image20210610094247295.png

这么看起来结果没有错,那么根据里氏替换原则的定义:一个软件实体如果适用一个父类的话,那一定是适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变

我们来将对象换成SumA的子类SumB的对象再来测试一下:

public static void main(String[] args) { SumA sumA = new SumB(); System.out.println("5 - 4 = "+sumA.reduce(5,4));}

结果:

image20210610094634682.png

可以看见结果发生了很大的变化,通过仔细查看代码我们发现SumA的两数相减方法reduce()SumB的两数相加方法reduce()名字相同。这么来就可以说SumB重写了SumA中的非抽象方法reduce(),并改变了reduce()方法的行为,使程序发生了很大的漏洞。所以我们来将SumB类进行改造:

public class SumB extends SumA { // 相加 public int add(int a,int b){  return a + b; }}

SumB类中增加一个add()方法,这样一来SumB作为子类,既可以调用自己类中的add()方法,也可以调用父类SumA中的reduce()方法。我们再来测试一下:

public static void main(String[] args) { SumB sumB = new SumB(); System.out.println("5 - 4 = "+sumB.reduce(5,4)); System.out.println("5 + 4 = "+sumB.add(5,4));}

image20210610095807092.png

当然也有人说,如果非要重写父类的方法该怎么办?我这边建议两个方法:

  1. 将现有的继承关系去掉,让SumASumB类都实现同一个接口Sum类,然后再重写Sum类中的reduce()方法。
  2. SumASumB都继承一个比较通俗的基类(父类),将现有的继承关系去掉,采用依赖、聚合,组合等关系代替。

二、合成复用原则

尽量使用对象组合/聚合,而不是使用继承达到软件复用的目的。可以使系统更加的灵活,降低类与类之间的耦合度,一个类的变化对于其他类来说影响相对较少。

继承我们称之为白箱复用,相当于把实现的细节暴露给子类,组合/聚合 也成为黑箱复用,对类之外的对象是无法获取到实现细节的。

合成复用原则的核心是:复用时要尽量使用组合/聚合关系(关联关系),少用继承

我们先来看一个数据库连接的例子:

// 数据库连接public class DBConnection { //MySQL数据连接 public String getConnection(){  return "MySQL数据库连接......"; }}
// 产品类 daopublic class ProductDAO { private DBConnection dbConnection; public void setDbConnection(DBConnection dbConnection) {  this.dbConnection = dbConnection; } public void addProduct(){  String connection = dbConnection.getConnection();  System.out.println("使用【"+connection+"】增加产品"); }}

DBConnection是一个提供数据库连接的类,目前只支持MySQL数据库连接的方法。某一天,客户要求增加一个Oracle数据库连接的产品,那我们先在DBConnection增加一个getOracleConnection()的方法,再去修改ProductDAO类中的代码?这里且不说已经违反了开闭原则,就是各种代码的复制粘贴也让人心烦的,完全不够简洁、优雅。

我们不用去修改ProductDAO类中的代码,只需要将DBConnection类的代码改动一下:

// 数据库连接public abstract class DBConnection { //数据库连接方法 public abstract String getConnection();}

如上面的代码,将DBConnection类改为抽象类,将getConnection()方法改为抽象方法。这样一来,如果我们需要MySQL数据库连接,就增加一个MySQLConnection类来继承DBConnection类:

public class MySQLConnection extends DBConnection { @Override public String getConnection() {  return "MySQL数据库连接......"; }}

如果我们需要Oracle数据库连接,就增加一个OracleConnection类来继承DBConnection类:

public class OracleConnection extends DBConnection { @Override public String getConnection() {  return "Oracle数据库连接......"; }}

最后在调用ProductDAO类中的addProduct()方法前,我们只需要调用setDbConnection()方法并传入我们所需要的DBConnection类的子类的对象就可以了。

类图:

image20210610104159716.png

最后


设计模式中的七大原则已经讲完了,共有四篇博客,感兴趣的朋友可以去我的博客空间看看。

从下一篇博客开始,我将开始讲解一下Java中常见的以及我们经常用到的一些设计模式,包括工厂模式、代理模式、单例......如果有兴趣的朋友可以继续关注我,让我们一同进步,谢谢!









原文转载:http://www.shaoqun.com/a/793524.html

跨境电商:https://www.ikjzd.com/

一淘网:https://www.ikjzd.com/w/1698

upc:https://www.ikjzd.com/w/111

海鹰数据:https://www.ikjzd.com/w/2539

淘粉吧官网:https://www.ikjzd.com/w/1725.html


里氏替换原则最核心得一句话就是:子类可以扩展基类(父类)的功能,但不能改变父类原有的功能。合成复用原则的核心是:复用时要尽量使用组合/聚合关系(关联关系),少用继承。一、里氏替换原则如果说实现开闭原则的关键步骤就是抽象化,那么基类(父类)和子类的继承关系就是抽象化的具体实现,所以里氏替换原则就是对实现抽象化的具体步骤的规范。即:子类可以扩展基类(父类)的功能,但不能改变父类原有的功能。定义:一个软
操作多个账号的小伙伴可以看看,亚马逊账号关联的原因及解决办法:https://www.ikjzd.com/tl/7992
亚马逊—Promotion 中的 percentage Off 促销教程:https://www.ikjzd.com/tl/7998
亚马逊:品牌备案流程详情一览表:https://www.ikjzd.com/tl/8001
hts:https://www.ikjzd.com/w/525
etoro:https://www.ikjzd.com/w/1402
吴佳:https://www.ikjzd.com/w/1770
口述:我出轨未遂成了丈夫风流的借口(5/5):http://lady.shaoqun.com/m/a/42707.html
我会轻点,不会能疼你的 嫂子梦幻般的呻吟使我无法忘怀:http://www.30bags.com/m/a/254947.html
东莞万江萌宠乐园门票2021年6月价格:http://www.30bags.com/a/370406.html
速卖通店铺如何设置优惠劵攻略:https://www.ikjzd.com/articles/145657
中国女性会被质疑为"双性恋者",国际田联会被迫解释!说谎会伤良心吗?:http://lady.shaoqun.com/a/363156.html
一个大学教室的不雅视频被曝光,被全网疯狂传播:放纵的生活有多可怕:http://lady.shaoqun.com/a/363157.html

没有评论:

发表评论

跨境电商资讯:外贸宣传平台有哪些(出口的

现在很多做外贸的人都非常关注 外贸企业怎么推广 ,而现在推广的途径和平台有很多,企业如果都做,成本和时间精力是一个问题,而且并不是所有的推广渠道都是有用的。今天云程网络就来为大家盘点几个有效的外贸推广渠道。 一、海外社交媒体营销 Facebook,领英等海外社交媒体营销在近几年得...