JAVA【设计模式】里氏替换原则
一、设计模式的规范
设计模式遵循六⼤原则;单⼀职责( ⼀个类和⽅法只做⼀件事 )、⾥⽒替换( 多态,⼦类可扩展⽗类 )、依赖
倒置( 细节依赖抽象,下层依赖上层 )、接⼝隔离( 建⽴单⼀接⼝ )、迪⽶特原则( 最少知道,降低耦合 )、开闭
原则( 抽象架构,扩展实现 ),会在具体的设计模式章节中,进⾏体现。
二、里氏替换原则
定义:父类所拥有的方法和属性,在子类上依然可以使用,逻辑成立
三、示例
模拟场景:
1、例如:你去吃海底捞,你去海底捞总部享有的服务和子公司海底捞是一样的,你还是会享有到上帝般的待遇,不可能你去吃子公司的海底捞,就让你刷盘端菜…
2、例如:银行卡
拥有存钱和取钱的功能,储蓄卡
也有存钱和取钱的功能,并且还有风险评估
的功能。信用卡
拥有储蓄卡
的所有功能,并且还能利用信用做小额贷款
和还款
功能。
里氏替换原则
银行卡
package com.qf.principle.lishireplacement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 银行卡
*/
public abstract class BankCard {
private Logger logger = LoggerFactory.getLogger(BankCard.class);
private String cardNo; // 卡号
private String cardDate; // 开卡时间
public BankCard(String cardNo, String cardDate) {
this.cardNo = cardNo;
this.cardDate = cardDate;
}
abstract boolean rule(BigDecimal amount);
// 正向入账,+ 钱
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<String>();
tradeList.add("100001,100.00");
tradeList.add("100001,80.00");
tradeList.add("100001,76.50");
tradeList.add("100001,126.00");
return tradeList;
}
public String getCardNo() {
return cardNo;
}
public String getCardDate() {
return cardDate;
}
}
储蓄卡
package com.qf.principle.lishireplacement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
/**
* @description: 模拟储蓄卡功能
*/
public class CashCard extends BankCard {
private Logger logger = LoggerFactory.getLogger(CashCard.class);
public CashCard(String cardNo, String cardDate) {
super(cardNo, cardDate);
}
boolean rule(BigDecimal amount) {
return true;
}
/**
* 提现
*
* @param orderId 单号
* @param amount 金额
* @return 状态码 0000成功、0001失败、0002重复
*/
public String withdrawal(String orderId, BigDecimal amount) {
// 模拟支付成功
logger.info("提现成功,单号:{} 金额:{}", orderId, amount);
return super.negative(orderId, amount);
}
/**
* 储蓄
*
* @param orderId 单号
* @param amount 金额
*/
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;
}
}
信用卡
package com.qf.principle.lishireplacement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
/**
* @description: 信用卡
*/
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);
}
}
package com.qf.principle.lishireplacement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
public class ApiTest {
private static Logger logger = LoggerFactory.getLogger(ApiTest.class);
public static void main(String[] args) {
logger.info("里氏替换前,CashCard类:");
CashCard bankCard = new CashCard("6214567800989876", "2022-03-05");
// 提现
bankCard.withdrawal("100001", new BigDecimal(100));
// 储蓄
bankCard.recharge("100001", new BigDecimal(100));
logger.info("里氏替换后,CreditCard类:");
CashCard creditCard = new CreditCard("6214567800989876", "2022-03-05");
// 提现
creditCard.withdrawal("100001", new BigDecimal(1000000));
// 储蓄
creditCard.recharge("100001", new BigDecimal(100));
/* CreditCard creditCard2 = new CreditCard("6214567800989876", "2022-03-05");
// 支付,贷款
creditCard2.loan("100001", new BigDecimal(100));
// 还款
creditCard2.repayment("100001", new BigDecimal(100));*/
}
}
总结:
里氏替换原则本质是开闭原则上面的进一步强调父类特性在子类的可用性。