里氏替换原则

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

里氏替换原则:

如果S是T的子类,那么所有T类型的对象都可以在不破换程序的情况下被S类型的对象替换

简单来说,子类可以扩展父类的功能,但是不能改变父类原有的功能。也就是说:当子类继承父类时,除了添加新的方法且完成新增功能外,尽量不能重新父类的方法。这句话包含了四点:

1.子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法

2.子类可以增加自己特有的方法

3.当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松

当子类的方法实现父类的方法(重载、重写或实现抽象方法)时,方法的后置条件(即方法的输出或者返回值)要比父类的方法更严格或者与父类的方法相等。

里氏替换原则的作用

1.里氏替换原则是实现开闭原则的重要的方式之一

2.解决了继承中的重写父类造成的可复用性变差的问题

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

4.加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性,可扩展性,降低需求变更时引入的风险

原始方法代码实现:

public class CashCard {

    /**
     * 在储蓄卡的功能实现中包括了三个方法:提现、储蓄、交易流水查询,这些都是模拟储蓄卡的基本功能
     */

    public Logger logger = LoggerFactory.getLogger(CashCard.class);

    /**
     * 提现
     * @param orderId 单号
     * @param amount 金额
     * @return 状态码 0000成功 0001 失败 0002 重复
     */
    public String withdrawal(String orderId, BigDecimal amount) {
        //模拟支付成功
        logger.info("提现成功,单号:{} 金额:{}",orderId,amount);
        return "0000";
    }


    /**
     * 储蓄
     * @param orderId 单号
     * @param amount 金额
     * @return 状态码
     */
    public String recharge(String orderId,BigDecimal amount) {
        //模拟充值功能
        logger.info("储蓄成功,单号:{} 金额:{}",orderId,amount);
        return "0000";
    }

    /**
     * 交易流水查询
     * @return
     */
    public List<String> tradeFlow() {
        logger.info("交易流水查询成功");
        List<String> tradeList = new ArrayList<>();
        tradeList.add("100001,100.00");
        tradeList.add("100001,80.00");
        tradeList.add("100001,76.00");
        tradeList.add("100001,126.00");
        return tradeList;
    }


}
public class CreditCard extends CashCard {
    private Logger logger = LoggerFactory.getLogger(CreditCard.class);

    /**
     * 贷款功能
     * @param orderId 单号
     * @param amount  金额
     * @return
     */
    @Override
    public String withdrawal(String orderId, BigDecimal amount) {
        //校验参数
        if (amount.compareTo(new BigDecimal(1000)) >= 0) {
            logger.info("贷款金额校验(限额1000元),单号:{} 金额:{}",orderId,amount);
            return "0001";
        }

        //模拟生成贷款单
        logger.info("生成贷款单,单号:{} 金额:{}",orderId,amount);
        //模拟支付成功
        logger.info("贷款成功,单号:{} 金额:{}" ,orderId,amount);
        return "0000";
    }

    /**
     * 还款功能
     * @param orderId 单号
     * @param amount  金额
     * @return
     */
    @Override
    public String recharge(String orderId, BigDecimal amount) {
        //模拟生成还款单
        logger.info("生成还款单,单号:{} 金额:{}" ,orderId,amount);
        //模拟还款成功
        logger.info("还款成功,订单号:{} 金额:{}",orderId,amount);
        return "0000";
    }

    /**
     * 打印信用卡流水详情
     * @return
     */
    @Override
    public List<String> tradeFlow() {
        return super.tradeFlow();
    }

    /**
     * 信用卡功能呢的实现是在继承了储蓄卡的类之后,进行方法的重写:支付方法,还款方法,打印流水方法
     * 其实也可以不用重写这个方法,可以复用
     */
}

里氏替换代码实现:

public abstract class BackCard {

    /**
     * 在抽象银行卡类中,提供了基本卡的属性,包括卡号、开卡时间、及三个核心方法。
     * 正向入账 加钱
     * 逆向入账 减钱
     * 查询交易流水
     */

    private Logger logger = LoggerFactory.getLogger(BackCard.class);

    private String cardNo; //卡号

    private String cardDate; //开卡时间

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

    //规则
    abstract boolean rule(BigDecimal amount);

    /**
     * 正向入账,加钱
     * @param orderId
     * @param amount
     * @return
     */
    public String positive(String orderId,BigDecimal amount) {
        //入款成功 存款、还款
        logger.info("卡号() 入款成功,单号:{} 金额:{}" ,cardNo,orderId,amount);
        return "0000";
    }

    public String negative(String orderId,BigDecimal amount){
        //出款成功,存款 还款
        logger.info("卡号() 出款成功,单号:{} 金额:{}" ,cardNo,orderId,amount);
        return "0000";
    }

    /**
     * 交易流水查询
     * @return
     */
    public List<String> tradeFlow(){
        logger.info("交易流水查询成功");
        List<String> tradeList = new ArrayList<>();
        tradeList.add("100001,100.00");
        tradeList.add("100001,80.00");
        tradeList.add("100001,76.00");
        tradeList.add("100001,126.00");
        return tradeList;
    }

    public String getCardNo(){
        return cardNo;
    }

    public String getCardDate(){
        return cardDate;
    }
}
public class BackTest {
    public static void main(String[] args) {
        CashCard backCard = new CashCard("966356985233366", "2022-02-22");

        //提现
        backCard.withdrawal("100001", new BigDecimal(100));

        //储存
        backCard.recharge("100001", new BigDecimal(100));
    }
}
public class CashCard extends BackCard {

    private Logger logger = LoggerFactory.getLogger(CashCard.class);

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

    /**
     * 规则过滤,储蓄卡直接默认通过
     * @param amount
     * @return
     */
    @Override
    boolean rule(BigDecimal amount) {
        return true;
    }

    /**
     * 提现
     * @param orderId
     * @param amount
     * @return
     */
    public String withdrawal(String orderId,BigDecimal amount) {
        //模拟支付成功
        logger.info("模拟体现成功,单号:{} 金额:{}" ,orderId,amount);
        return super.negative(orderId,amount);
    }

    /**
     * 储蓄
     * @param orderId
     * @param amount
     * @return
     */
    public String recharge(String orderId,BigDecimal amount) {
        //模拟储蓄成功
        logger.info("储蓄成功,订单号:{} 金额:{}",orderId,amount);
        return super.positive(orderId, amount);
    }

    /**
     * 功能增强  风险校验
     * @param cardNo 卡号
     * @param orderId 单号
     * @param amount 金额
     * @return 状态
     */
    public boolean checkRisk(String cardNo,String orderId,BigDecimal amount){
        //模拟风控校验
        logger.info("风控校验,卡号{} 单号:{} 金额:{}",cardNo,orderId,amount);
        return true;
    }

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

}
public class CreditCard extends CashCard {
    private Logger logger = LoggerFactory.getLogger(CreditCard.class);

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

    boolean rule2(BigDecimal amount) {
        return amount.compareTo(new BigDecimal(1000)) <= 0;
    }

    /**
     * 提现,信用卡贷款
     * @param orderId
     * @param amount
     * @return
     */
    public String loan(String orderId,BigDecimal amount) {
        boolean rule = rule2(amount);

        if (!rule) {
            logger.info("生成贷款单失败,金额超限。单号:{} 金额:{}",orderId,amount);
            return "0001";
        }
        //模拟生成贷款
        logger.info("生成贷款单,单号:{} 金额:{}",orderId,amount);
        //模拟支付成功
        logger.info("贷款成功,单号:{} 金额:{}",orderId,amount);
        return super.negative(orderId, amount);

    }


    /**
     * 还款 信用卡还款
     * @param orderId
     * @param amount
     * @return
     */
    public String repayment(String orderId,BigDecimal amount) {
        //模拟生成还款单
        logger.info("生成还款单,单号:{} 金额:{}",orderId,amount);
        //模拟还款成功
        logger.info("还款成功,单号:{} 金额:{}",orderId,amount);
        return super.positive(orderId, amount);
    }

    /**
     * 信用卡类在继承了储蓄卡类之后,使用了公共的属性,即卡号 开卡时间 同时新增了符合信用卡功能的新方法,即贷款、还款,并在两个方法中都使用了抽象类的核心功能
     */
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值