网站综合建设笔记,商洛市住房和城乡建设局网站,海口市住房和城乡建设局网站,房地产官网#x1f973;#x1f973;#x1f973; 茫茫人海千千万万#xff0c;感谢这一刻你看到了我的文章#xff0c;感谢观赏#xff0c;大家好呀#xff0c;我是最爱吃鱼罐头#xff0c;大家可以叫鱼罐头呦~#x1f973;#x1f973;#x1f973; 从今天开始#xff0c;将… 茫茫人海千千万万感谢这一刻你看到了我的文章感谢观赏大家好呀我是最爱吃鱼罐头大家可以叫鱼罐头呦~ 从今天开始将开启一个专栏【贯穿设计模式】设计模式是对软件设计中普遍存在反复出现的各种问题所提出的解决方案是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。为了能更好的设计出优雅的代码为了能更好的提升自己的编程水准为了能够更好的理解诸多技术的底层源码 设计模式就是基石万丈高楼平地起,一砖一瓦皆根基。 ✨✨欢迎订阅本专栏✨✨ 本人不才如果文章知识点有缺漏、错误的地方 也欢迎各位人才们评论批评指正和大家一起学习一起进步! ❤️ 愿自己还有你在未来的日子保持学习保持进步保持热爱奔赴山海 ❤️ 最后希望我的这篇文章能对你的有所帮助 点赞 收藏 ⭐留言 都是我最大的动力 前言回顾 【贯穿设计模式】第一话·设计模式初介绍和单一职责原则 【贯穿设计模式】第二话·设计模式的七大原则之开闭原则 【贯穿设计模式】第三话·设计模式的七大原则之依赖倒转 在第三篇文章中我们了解设计模式的七大原则中第三个原则依赖倒转原则
我们来回顾下它的定义高层模块不应该依赖低层模块两者都应该依赖其抽象抽象不应该依赖细节细节应该依赖抽象依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中尽量引用层次高的抽象层类。
并且我们通过上学时每个学期可能上课的不同导致如果需要再学习一门新课程的需求导致代码的修改等问题值得注意的是在实现依赖倒转原则时需要针对抽象层编程而将具体类的对象通过依赖注入的方式注入其他对象中。依赖注入是指当一个对象要与其他对象发生依赖关系时通过抽象来注入所依赖的对象。而常用的注入方式有3种接口注入、构造注入和Setter注入。
⭐ 前提需要 在面向对象的语言中继承是必不可少的它主要有以下几个优点 代码共享减少创建类的工作量每个子类都拥有父类的方法和属性提高代码的可重用性提高代码的可扩展性提高产品或项目的开放性。 相应的继承也存在缺点主要体现在以下几个方面 继承是入侵式的。只要继承就必须拥有父类的所有属性和方法降低代码的灵活性。子类必须拥有父类的属性和方法使子类受到限制增强了耦合性。当父类的常量、变量和方法修改时必须考虑子类的修改这种修改可能造成大片的代码需要重构。从整体上看继承的“利”大于“弊”然而如何让继承中“利”的因素发挥最大作用同时减少“弊”所带来的麻烦这就需要引入“里氏替换原则”。 里氏替换原则 今天我们学习的是里氏替换原则任何基类可以出现的地方子类一定可以出现。 概述 该原则是指任何基类可以出现的地方子类一定可以出现即所有引用基类的地方都必须能够透明的使用其子类里氏替换原则是继承与复用的基石只有当子类可以替换掉基类且系统的功能不受影响时基类才能被复用而子类也能够在基础类上增加新的行为所以里氏替换原则指的是任何基类可以出现的地方子类一定可以出现 里氏替换原则是对开闭原则的补充实现开闭原则的关键步骤就是抽象化而基类与子类的继承关系就是抽象化的具体实现所以里氏替换原则是对实现抽象化的具体步骤的规范 简单理解就是子类继承父类时除添加新的方法完成新增功能外尽量不要重写父类的方法如果子类强制要重写父类的方法那么可以再抽象一个基类为他们的公共父类或采用依赖、组合、聚合的方式来实现 比如有一个基类A有个实现了的方法其子类B、C等都可以完全替换A类来实现但不能影响原有的代码功能如果子类B、C需要重写父类的方法的话就会导致子类B、C不能完全替换基类A来使用了此时应该可以再抽象一个基类为他们的公共父类或采用依赖、组合、聚合的方式来实现。 特点
里氏替换原则是实现开闭原则的重要方式之一通过里氏替换可以使系统有以下优点
解决了继承中重写父类造成的可复用性变差的问题是动作正确性的保证即类的扩展不会给已有的系统引入新的错误降低了代码出错的可能性加强程序的健壮性同时变更时可以做到非常好的兼容性提高程序的维护性、可扩展性降低需求变更时引入的风险。 问题引出 在上Java相关课程时学习面向对象的时候老师都会提动物、猫、狗之间的关系都会说他们之间的抽象关系或者继承关系那接下来就以动物的例子来形象的讲解里氏替换原则吧。
1. 定义一个鸟类Bird 对于鸟类来说我们对此的第一印象就是鸟类都是能飞的。 package com.ygt.principle.lsp;/*** 新建一个鸟类* 鸟类有个方法是可以非的方法*/
public class Bird {// 鸟的名字private String name;// 构造方法public Bird(String name) {this.name name;}public void fly(){System.out.println(this.name 开始飞啦~~~);}
}2. 定义一个百灵鸟类Lark并继承鸟类的飞行的方法
package com.ygt.principle.lsp;/*** 创建一个百灵鸟类继承鸟类*/
public class Lark extends Bird{public Lark(String name) {super(name);}
}3. 建立一个测试类LiskovSubstitutionTest测试一下百灵鸟的飞行
package com.ygt.principle.lsp;/*** 测试里氏替换原则*/
public class LiskovSubstitutionTest {public static void main(String[] args) {// 创建百灵鸟并让其有飞的动作Lark lark new Lark(百灵鸟);lark.fly();}
}4. 得到的结果
百灵鸟开始飞啦~~~5. 现在新建一个鸵鸟类Ostrich并继承鸟类
package com.ygt.principle.lsp;/*** 建立一个鸵鸟类并继承鸟类*/
public class Ostrich extends Bird{public Ostrich(String name) {super(name);}
}6. 测试鸵鸟的飞行功能
package com.ygt.principle.lsp;/*** 测试里氏替换原则*/
public class LiskovSubstitutionTest {public static void main(String[] args) {// 创建百灵鸟并让其有飞的动作Lark lark new Lark(百灵鸟);lark.fly();// 创建鸵鸟测试其飞行功能Ostrich ostrich new Ostrich(鸵鸟);ostrich.fly();}
}7. 得到的结果
百灵鸟开始飞啦~~~
鸵鸟开始飞啦~~~可是现在有个问题我们知道普遍的鸟类动物都是善于飞翔的但是也有些鸟类是不会飞行的就如鸵鸟、企鹅一般的鸟类是不会飞行的那此时我们在代码中将其继承鸟类是不合理的因为如果要在鸵鸟类中重写修改飞行方法的话这就务必导致违反了里氏替换原则了我们将不能使用鸵鸟类来替换成鸟类来使用了。下面我们就一起来看看解决方案吧。 解决方案
在上面的时候说过当然我们也可以重写飞行的方法使鸵鸟的飞行功能是无的但是这就破坏了里氏替换原则也会导致整个系统的可复用性变差这时常用的解决方案就是取消原来的继承关系重新设计他们之间的关系即使原来的父类鸟类和子类鸵鸟类都继承一个更通俗的基类动物类这样原来的继承关系去掉最后采用依赖聚合组合等关系代替。
1. 定义一个动物类Animal
package com.ygt.principle.lsp;/*** 定义一个动物类*/
public class Animal {// 动物的名称public String name;public Animal(String name) {this.name name;}
}2. 修改鸟类、鸵鸟类和测试类
package com.ygt.principle.lsp;/*** 新建一个鸟类* 鸟类有个方法是可以非的方法* 修改如下继承自动物类*/
public class Bird extends Animal {public Bird(String name) {super(name);}public void fly(){System.out.println(super.name 开始飞啦~~~);}
}package com.ygt.principle.lsp;/*** 建立一个鸵鸟类并继承鸟类* 修改如下不继承鸟类改继承动物类*/
public class Ostrich extends Animal{// 如果还想使用鸟类的属性以及方法可以采用依赖方式private Bird bird;public Ostrich(String name) {super(name);}public void run(){System.out.println(name 开始奔跑****);}
}package com.ygt.principle.lsp;/*** 测试里氏替换原则*/
public class LiskovSubstitutionTest {public static void main(String[] args) {// 创建百灵鸟并让其有飞的动作Lark lark new Lark(百灵鸟);lark.fly();// 创建鸵鸟测试其飞行功能Ostrich ostrich new Ostrich(鸵鸟);ostrich.run();}
}得到的结果
百灵鸟开始飞啦~~~
鸵鸟开始奔跑****这样我们通过使原来的鸟类和鸵鸟都继承一个新的基类Animal类后这就排除了修改鸟类中的飞行方法了如果还需要使用鸟类中的功能可以通过依赖、聚合组合等关系代替。
而我们在实际编程中常常会通过重写父类的方法来完成新的功能这样写起来虽然简单但是整个继承体系的可复用性会比较差特别是运用多态比较频繁时程序运行出错的几率非常大。 完结
相信各位看官看到这里大致都对设计模式中的其中一个原则有了了解吧里氏替换原则指任何基类可以出现的地方子类一定可以出现即所有引用基类的地方都必须能够透明的使用其子类里氏替换原则是继承与复用的基石里氏替换原则是对实现抽象化的具体步骤的规范。
学好设计模式让你感受一些机械化代码之外的程序设计魅力也可以让你理解各个框架底层的实现原理。最后祝大家跟自己能在程序员这条越走越远呀祝大家人均架构师我也在努力。 接下来期待第五话接口隔离原则。
文章的最后来个小小的思维导图 本人不才如有什么缺漏、错误的地方也欢迎各位人才们评论批评指正 当然如果这篇文章确定对你有点小小帮助的话也请亲切可爱的人才们给个点赞、收藏下吧非常感谢 虽然这篇文章完结了但是我还在永不完结。我会努力保持写文章。来日方长何惧车遥马慢✨✨✨ 感谢各位看到这里愿你韶华不负青春无悔让我们一起加油吧 学到这里今天的世界打烊了晚安