搞定里式替换原则的设计模式一篇文章就够了!!!

Posted 南淮北安

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞定里式替换原则的设计模式一篇文章就够了!!!相关的知识,希望对你有一定的参考价值。

一、定义

继承必须确保父类所拥有的性质在子类中仍然成立

子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:当子类继承父类时,除添加新的方法且完成新增功能外,尽量不要重写父类的方法。

是动作正确性的保证,即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。

二、示例问题

我们会使用各种类型的银行卡,例如储蓄卡、信用卡,还有一些其他特性的银行卡。储蓄卡和信用卡都具备一定的消费功能,但又有一些不同。例如信用卡不宜提现,如果提现可能会产生高额的利息。

下面构建这样一个模拟场景,假设在构建银行系统时,储蓄卡是第一个类,信用卡是第二个类。为了让信用卡可以使用储蓄卡的一些方法,选择由信用卡类继承储蓄卡类,讨论是否满足里氏替换原则产生的一些要点。

储蓄卡和信用卡在使用功能上类似,都有支付、提现、还款、充值等功能,也有些许不同,例如支付,储蓄卡做的是账户扣款动作,信用卡做的是生成贷款单动作。

下面这里模拟先有储蓄卡的类,之后继承这个类的基本功能,以实现信用卡的功能。

public class CashCard {
    
    public void withdrawal(String orderId, BigDecimal amount) {
        System.out.println("模拟提现");
    }

    public void recharge(String orderId, BigDecimal amount) {
        System.out.println("模拟储蓄");
    }
    
    public void tradeFlow(){
        System.out.println("模拟流水查询");
    }
}

储蓄卡的基本功能:提现,储蓄,流水查询

信用卡继承储蓄卡,重新提现和储蓄的功能,复用流水查询的功能

public class CreditCard extends CashCard{
    @Override
    public void withdrawal(String orderId, BigDecimal amount) {
        System.out.println("模拟贷款");
    }

    @Override
    public void recharge(String orderId, BigDecimal amount) {
        System.out.println("模拟还款");
    }

    @Override
    public void tradeFlow() {
        super.tradeFlow();
    }
}

这种继承父类方式的优点是复用了父类的核心功能逻辑,但是也破坏了原有的方法。

此时继承父类实现的信用卡类并不满足里氏替换原则,也就是说,此时的子类不能承担原父类的功能,直接给储蓄卡使用

三、问题改进

储蓄卡和信用卡在功能使用上有些许类似,在实际的开发过程中也有很多共同可复用的属性及逻辑。

实现这样的类的最好方式是提取出一个抽象类,由抽象类定义所有卡的共用核心属性、逻辑

抽象银行卡类:

public abstract class BankCard {
    // 卡号
    private String cardNo;
    // 开卡时间
    private String cardDate;

    public BankCard(String cardNo, String cardDate) {
        this.cardNo = cardNo;
        this.cardDate = cardDate;
    }

    public void tradeFlow() {
        System.out.println("模拟流水查询");
    }
}

储蓄卡类实现:

public class CashCard extends BankCard {

    public CashCard(String cardNo, String cardDate) {
        super(cardNo, cardDate);
    }

    public void withdrawal(String orderId, BigDecimal amount) {
        System.out.println("模拟提现");
    }

    public void recharge(String orderId, BigDecimal amount) {
        System.out.println("模拟储蓄");
    }
}

储蓄卡类中继承抽象银行卡父类 BankCard,实现的核心功能提现withdrawal、储蓄recharge

这样的实现方式满足了里氏替换的基本原则,既实现抽象类的抽象方法,又没有破坏父类中的原有方法。

接下来实现信用卡的功能,信用卡的功能可以继承于储蓄卡,也可以继承抽象银行卡父类。但无论哪种实现方式,都需要遵从里氏替换原则,不可以破坏父类原有的方法。

信用卡类实现:

public class CreditCard extends CashCard {

    public CreditCard(String cardNo, String cardDate) {
        super(cardNo, cardDate);
    }

    public void loan(String orderId, BigDecimal amount) {
        System.out.println("模拟贷款");
    }

    public void repayment(String orderId, BigDecimal amount) {
        System.out.println("模拟还款");
    }
}

信用卡类在继承父类后,使用了公用的属性,即卡号 cardNo、开卡时间cardDate,同时新增了符合信用卡功能的新方法,即贷款loan、还款repayment,并在两个方法中都使用了抽象类的核心功能。

以上的实现方式都是在遵循里氏替换原则下完成的,子类随时可以替代储蓄卡类。

以上是关于搞定里式替换原则的设计模式一篇文章就够了!!!的主要内容,如果未能解决你的问题,请参考以下文章

搞定设计模式之接口隔离原则一篇文章就够了!!!

搞定开闭原则的设计模式一篇文章就够了!!!

搞定设计模式之迪米特法则一篇文章就够了!!!

设计原则之里式替换原则

搞定设计模式之工厂模式一篇文章就够了!!!

搞定单一职责的设计模式一篇文章就够了!!!