一、设计模式里氏替换原则定义
里氏替换原则是面向对象设计的基本原则之一。 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏替换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。
二 、原则作用
- 里氏替换原则是实现开闭原则的重要方式之一。
- 它克服了继承中重写父类造成的可复用性变差的缺点。
- 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
- 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。
里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能
也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
根据上述理解,对里氏替换原则的定义可以总结如下:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
- 子类中可以增加自己特有的方法
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松
- 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等
三、原则实现实例
1、新建main.java空白文件,cursor输入指令
2、自动生成代码以及文件
2.1、Main.java代码如下:
public class Main {
public static void main(String[] args) {
PaymentProcessor creditCardProcessor = new CreditCardProcessor("1234-5678-9012-3456");
OrderProcessor creditCardOrder = new OrderProcessor(creditCardProcessor);
System.out.println("Processing credit card order:");
creditCardOrder.processOrder(100.00);
creditCardOrder.refundOrder(100.00);
System.out.println("\n----------------------------\n");
PaymentProcessor payPalProcessor = new PayPalProcessor("example@email.com");
OrderProcessor payPalOrder = new OrderProcessor(payPalProcessor);
System.out.println("Processing PayPal order:");
payPalOrder.processOrder(50.00);
payPalOrder.refundOrder(50.00);
}
}
2.2、PaymentProcessor.java代码如下:
PaymentProcessor 接口定义了所有支付处理器的通用行为。
public interface PaymentProcessor {
boolean processPayment(double amount);
void refund(double amount);
String getPaymentMethod();
}
2.3、CreditCardProcessor.java代码如下:
public class CreditCardProcessor implements PaymentProcessor {
private String cardNumber;
public CreditCardProcessor(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public boolean processPayment(double amount) {
System.out.println("Processing credit card payment of $" + amount);
// 实际实现中,这里会有信用卡支付的逻辑
return true;
}
@Override
public void refund(double amount) {
System.out.println("Refunding $" + amount + " to credit card");
// 实际实现中,这里会有退款到信用卡的逻辑
}
@Override
public String getPaymentMethod() {
return "Credit Card";
}
}
2.4、PayPalProcessor.java代码如下:
public class PayPalProcessor implements PaymentProcessor {
private String email;
public PayPalProcessor(String email) {
this.email = email;
}
@Override
public boolean processPayment(double amount) {
System.out.println("Processing PayPal payment of $" + amount);
// 实际实现中,这里会有PayPal支付的逻辑
return true;
}
@Override
public void refund(double amount) {
System.out.println("Refunding $" + amount + " to PayPal account");
// 实际实现中,这里会有退款到PayPal账户的逻辑
}
@Override
public String getPaymentMethod() {
return "PayPal";
}
}
2.5、OrderProcessor 类代码如下:
OrderProcessor 类接受任何 PaymentProcessor 对象,并能正确处理它们的行为。
public class OrderProcessor {
private PaymentProcessor paymentProcessor;
public OrderProcessor(PaymentProcessor paymentProcessor) {
this.paymentProcessor = paymentProcessor;
}
public boolean processOrder(double amount) {
boolean paymentSuccess = paymentProcessor.processPayment(amount);
if (paymentSuccess) {
System.out.println("Order processed successfully using " + paymentProcessor.getPaymentMethod());
return true;
} else {
System.out.println("Order processing failed");
return false;
}
}
public void refundOrder(double amount) {
paymentProcessor.refund(amount);
System.out.println("Order refunded using " + paymentProcessor.getPaymentMethod());
}
}
3、运行主程序输出
在 Main 类中,我们可以用 CreditCardProcessor 或 PayPalProcessor 对象替换 PaymentProcessor 类型的变量,而不会影响程序的正确性。
这个例子展示了如何在不同类型的支付处理器之间进行替换,而不影响使用这些处理器的代码。这种设计允许我们轻松地添加新的支付方式,而不需要修改现有的 OrderProcessor 类。