设计模式之七大原则(二)——里氏替换原则、依赖倒转原则

设计模式之七大原则(二)——里氏替换原则、依赖倒转原则文章讨论了里氏替换原则 LSP 和依赖倒转原则 DIP 在软件设计中的重要性

大家好,欢迎来到IT知识分享网。

1.里氏替换原则

里氏替换原则优点

  1. 约束继承泛滥,它也是开闭原则的一种很好的体现。
  2. 提高了代码的重用性。
  3. 降低了系统的出错率。类的扩展不会给原类造成影响,降低了代码出错的范围和系统出错的概率。
  4. 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。

里氏替换原则的实现方法
  里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。

public class Number { 
    public static void main(String[] args) { 
    A a = new A(); System.out.println("10-5=" + a.func(10, 5)); System.out.println("6-10=" + a.func(6, 10)); System.out.println("-----------------------"); B b = new B(); //本意是求出 11-3 和 1-8 但是由于重写改变了之前的职责 System.out.println("10-8=" + b.func(10, 8)); System.out.println("10-50=" + b.func(10, 50)); } } //类 A class A { 
    // 返回两个数的差 public int func(int a, int b) { 
    return a - b; } } class B extends A { 
    //重写了 A 类的方法, 可能是无意识 public int func(int a, int b) { 
    return a + b; } } 

运行结果如下所示:

10-5=5 6-10=-4 ----------------------- 10-8=18 10-50=60 

造成这样的结果,原因就是类 B 无意中重写了父类的方法,造成原有功能出现错误。

public class NumberLSP { 
    public static void main(String[] args) { 
    A1 a = new A1(); System.out.println("10-5=" + a.func(10, 5)); System.out.println("6-10=" + a.func(6, 10)); B1 b = new B1(); //因为 B 类不再继承 A 类,因此调用者,不会再 func 是求减法 ,调用会很明确 System.out.println("10-8=" + b.func(10, 8)); System.out.println("10-50=" + b.func(10, 50)); //使用组合仍然可以使用到 A 类相关方法 System.out.println("18-6=" + b.func2(18, 6)); } } //创建一个更加基础的基类 class Base { 
    //把更加基础的方法和成员写到 Base 类 } //类 A class A1 extends Base { 
    // 返回两个数的差 public int func(int a, int b){ 
    return a - b; } } class B1 extends Base { 
    //如果 B 需要使用 A 类的方法,使用组合关系 private A1 a = new A1(); //重写了 A 类的方法, 可能是无意识 public int func(int a, int b){ 
    return a + b; } public int func2(int a, int b){ 
    return this.a.func(a, b); } } 

运行结果如下所示:

10-5=5 6-10=-4 10-8=18 10-50=60 18-6=12 

2.依赖倒转原则

  依赖倒置原则的原始定义为:上层模块不应该依赖下层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象,其核心思想是:要面向接口编程,不要面向实现编程。

依赖倒置原则的定义

  1. 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  2. 抽象不应该依赖细节,细节应该依赖抽象
  3. 依赖倒置的中心思想是面向接口编程
  4. 依赖倒置原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
  5. 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

  作用

  1. 可以降低类间的耦合性。
  2. 可以提高系统的稳定性。
  3. 可以减少并行开发引起的风险。
  4. 可以提高代码的可读性和可维护性。

  实现方法
使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给它们的实现类去完成。所以我们在实际编程中只要遵循以下4点,就能在项目中满足这个规则。

  1. 每个类尽量提供接口或抽象类,或者两者都具备。
  2. 变量的声明类型尽量是接口或者是抽象类。
  3. 任何类都不应该从具体类派生。
  4. 使用继承时尽量遵循里氏替换原则。
public class Dependecy { 
    public static void main(String[] args) { 
    Person person = new Person(); person.receive(new Email()); } } class Email { 
    public String getInfo() { 
    return "邮件信息: hello,world"; } } class Person { 
    public void receive(Email email ) { 
    System.out.println(email.getInfo()); } } //增加微信 class WeiXin { 
    public String getInfo() { 
    return "微信信息: hello,world"; } } 

运行结果如下所示:

邮件信息: hello,world 
public class DependecyDIP { 
    public static void main(String[] args) { 
    //客户端无需改变 Person person = new Person(); person.receive(new Email()); person.receive(new WeiXin()); } } class Person { 
    //这里我们是对接口的依赖 public void receive(IReceiver receiver ) { 
    System.out.println(receiver.getInfo()); } } //增加微信 class WeiXin implements IReceiver { 
    public String getInfo() { 
    return "微信信息: hello,world"; } } class Email implements IReceiver { 
    public String getInfo() { 
    return "邮件信息: hello,world"; } } //定义接口 interface IReceiver { 
    public String getInfo(); } 

运行结果如下所示:

邮件信息: hello,world 微信信息: hello,world 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/142858.html

(0)
上一篇 2025-05-07 17:15
下一篇 2025-05-07 17:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信