- 浏览: 661527 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (609)
- java (139)
- 数据库 (107)
- 微信 (23)
- IT生活 (5)
- web前端 (74)
- SSH (11)
- 设计模式 (12)
- 重要资料 (11)
- 其他 (15)
- java技巧 (23)
- 服务器 (9)
- 2D/GUI (3)
- JAVA3D (2)
- ANT (5)
- Apache项目 (19)
- 数据类型 (10)
- 报表 (3)
- Collections (6)
- SQL/JDBC (15)
- 开发类 (6)
- EJB (6)
- Email (6)
- 文件读写 (2)
- 游戏 (0)
- Flex (2)
- Generic (2)
- HIbernate (12)
- I18N (5)
- Java EE (9)
- java ME (4)
- JDK 6 (8)
- JNDI/LDAP (5)
- JSP (7)
- JSTL (2)
- 正则表达式 (2)
- 安全 (2)
- Struts2 (12)
- Spring (4)
- Web服务 (10)
- Xml (1)
- JavaScript (30)
- AJAX (7)
- 验证 (4)
- 上传下载 (1)
- office办公软件 (1)
- Android (2)
- IOS (0)
- Dubbo (3)
- memcached/redis (1)
- 小程序 (1)
- 微信公众号 (0)
最新评论
-
wf_wangfeng:
怎么我用第一种方法不行呢 alert(document.rea ...
当jsp页面完全加载完成后执行一个js函数 -
Lori_Liu:
有帮助,至少可以解决了目前所遇到的问题!谢谢..
当jsp页面完全加载完成后执行一个js函数 -
starbhhc:
String actionMessage = new Stri ...
Java读取txt文件乱码 -
starbhhc:
Sev7en_jun 写道GOOD
客气,互相交流。。
javaeye论坛规则小测验(答案)--star -
Sev7en_jun:
GOOD
javaeye论坛规则小测验(答案)--star
原则:子类型必须能够替换它的基类型。
这就是著名的Liskov替换原则(LSP),又称里氏替换原则。
对于这个原则,通俗一些的理解就是,父类的方法都要在子类中实现或者重写,不允许子类出现父类所没有定义的方法。
我们前面说过依赖颠倒原则,说的是父类不能依赖子类,它们都要依赖抽象类。我们说这种依赖是我们实现代码扩展和运行期内绑定(多态)的基础。因为一旦类的使用者依赖某个具体的类,那么对该依赖的扩展就无从谈起;而依赖某个抽象类,则只要实现了该抽象类的子类,都可以被类的使用者使用,从而实现了系统的扩展。
但是,光有依赖颠倒原则,并不一定就使我们的代码真正具有良好的扩展性和运行期内绑定。请看下面的代码:
public class Animal
{
private String name;
public Animal(String name)
{
this.name = name;
}
public void descriptiion()
{
System.out.println(“This is a(an) ”+name);
}
}
下面是它的子类:
public class Cat extends Animal
{
public Cat(String name)
{
super(name);
}
public void mew()
{
System.out.println(“The cat is saying like ‘mew’”);
}
}
然后我们来看看Dog的实现:
public class Dog extends Animal
{
public Dog(String name)
{
super(name);
}
public void bark()
{
System.out.println(“The dog is saying like ‘bark’”);
}
}
最后,我们来看客户端的调用:
public decriptionTheAnimal(Animal animal)
{
if(animal instanceof Cat)
{
Cat cat = (Cat)animal;
Cat.decription();
Cat.mew();
}
else if(animal instanceof Dog)
{
Dog dog = (Dog)animal;
Dog.decription();
Dog.bark();
}
}
通过上面的代码,我们可以看到虽然客户端的依赖是对抽象的依赖,但依然这个设计的扩展性不好,运行期绑定没有实现。
是什么原因呢?其实就是因为不满足里氏替换原则,子类如Cat有mew()方法父类根本没有,Dog类有bark()方法父类也没有,两个子类都不能替换父类。这样导致了系统的扩展性不好和没有实现运行期内绑定。
现在看来,一个系统或子系统要拥有良好的扩展性和实现运行期内绑定,有两个必要条件:第一是依赖颠倒原则;第二是里氏替换原则。这两个原则缺一不可。
里氏替换原则的好处:
第一、保证系统或子系统有良好的扩展性。只有子类能够完全替换父类,才能保证系统或子系统在运行期内识别子类就可以了,因而使得系统或子系统有了良好的扩展性。
第二、实现运行期内绑定,即保证了面向对象多态性的顺利进行。这节省了大量的代码重复或冗余。避免了类似instanceof这样的语句,或者getClass()这样的语句,这些语句是面向对象所忌讳的。
第三、有利于实现契约式编程。契约式编程有利于系统的分析和设计,指我们在分析和设计的时候,定义好系统的接口,然后再编码的时候实现这些接口即可。在父类里定义好子类需要实现的功能,而子类只要实现这些功能即可。
我们知道,在我们的大多数的模式中,我们都有一个共同的接口,然后子类和扩展类都去实现该接口。这里,我们以命令模式为例。
下面是一段原始代码:
if(action.equals(“add”))
{
//do add action
……
}
else if(action.equals(“view”))
{
//do view action
……
}
else if(action.equals(“delete”))
{
//do delete action
……
}
else if(action.equals(“modify”))
{
//do modify action
……
}
我们首先想到的是把这些动作分离出来,就可能写出如下的代码:
public class AddAction
{
public void add()
{
//do add action
……
}
}
public class ViewAction
{
public void view()
{
//do view action
……
}
}
public class deleteAction
{
public void delete()
{
//do delete action
……
}
}
public class ModifyAction
{
public void modify()
{
//do modify action
……
}
}
我们可以看到,这样代码将各个行为独立出来,满足了单一职责原则,但这远远不够,因为它不满足依赖颠倒原则和里氏替换原则。
下面我们来看看命令模式对该问题的解决方法:
首先是定义一个接口:
public interface Action
{
public void doAction();
}
然后是各个实现:
public class AddAction implements Action
{
public void doAction()
{
//do add action
……
}
}
public class ViewAction implements Action
{
public void doAction()
{
//do view action
……
}
}
public class deleteAction implements Action
{
public void doAction()
{
//do delete action
……
}
}
public class ModifyAction implements Action
{
public void doAction()
{
//do modify action
……
}
}
这样,客户端的调用大概如下:
public void execute(Action action)
{
action.doAction();
}
看,上面的客户端代码再也没有出现过instanceof这样的语句,扩展性良好,也有了运行期内绑定的优点。
在这里,只拿出命令模式一个模式来作为例子来看看模式是怎么遵从里氏替换原则的!
这就是著名的Liskov替换原则(LSP),又称里氏替换原则。
对于这个原则,通俗一些的理解就是,父类的方法都要在子类中实现或者重写,不允许子类出现父类所没有定义的方法。
我们前面说过依赖颠倒原则,说的是父类不能依赖子类,它们都要依赖抽象类。我们说这种依赖是我们实现代码扩展和运行期内绑定(多态)的基础。因为一旦类的使用者依赖某个具体的类,那么对该依赖的扩展就无从谈起;而依赖某个抽象类,则只要实现了该抽象类的子类,都可以被类的使用者使用,从而实现了系统的扩展。
但是,光有依赖颠倒原则,并不一定就使我们的代码真正具有良好的扩展性和运行期内绑定。请看下面的代码:
public class Animal
{
private String name;
public Animal(String name)
{
this.name = name;
}
public void descriptiion()
{
System.out.println(“This is a(an) ”+name);
}
}
下面是它的子类:
public class Cat extends Animal
{
public Cat(String name)
{
super(name);
}
public void mew()
{
System.out.println(“The cat is saying like ‘mew’”);
}
}
然后我们来看看Dog的实现:
public class Dog extends Animal
{
public Dog(String name)
{
super(name);
}
public void bark()
{
System.out.println(“The dog is saying like ‘bark’”);
}
}
最后,我们来看客户端的调用:
public decriptionTheAnimal(Animal animal)
{
if(animal instanceof Cat)
{
Cat cat = (Cat)animal;
Cat.decription();
Cat.mew();
}
else if(animal instanceof Dog)
{
Dog dog = (Dog)animal;
Dog.decription();
Dog.bark();
}
}
通过上面的代码,我们可以看到虽然客户端的依赖是对抽象的依赖,但依然这个设计的扩展性不好,运行期绑定没有实现。
是什么原因呢?其实就是因为不满足里氏替换原则,子类如Cat有mew()方法父类根本没有,Dog类有bark()方法父类也没有,两个子类都不能替换父类。这样导致了系统的扩展性不好和没有实现运行期内绑定。
现在看来,一个系统或子系统要拥有良好的扩展性和实现运行期内绑定,有两个必要条件:第一是依赖颠倒原则;第二是里氏替换原则。这两个原则缺一不可。
里氏替换原则的好处:
第一、保证系统或子系统有良好的扩展性。只有子类能够完全替换父类,才能保证系统或子系统在运行期内识别子类就可以了,因而使得系统或子系统有了良好的扩展性。
第二、实现运行期内绑定,即保证了面向对象多态性的顺利进行。这节省了大量的代码重复或冗余。避免了类似instanceof这样的语句,或者getClass()这样的语句,这些语句是面向对象所忌讳的。
第三、有利于实现契约式编程。契约式编程有利于系统的分析和设计,指我们在分析和设计的时候,定义好系统的接口,然后再编码的时候实现这些接口即可。在父类里定义好子类需要实现的功能,而子类只要实现这些功能即可。
我们知道,在我们的大多数的模式中,我们都有一个共同的接口,然后子类和扩展类都去实现该接口。这里,我们以命令模式为例。
下面是一段原始代码:
if(action.equals(“add”))
{
//do add action
……
}
else if(action.equals(“view”))
{
//do view action
……
}
else if(action.equals(“delete”))
{
//do delete action
……
}
else if(action.equals(“modify”))
{
//do modify action
……
}
我们首先想到的是把这些动作分离出来,就可能写出如下的代码:
public class AddAction
{
public void add()
{
//do add action
……
}
}
public class ViewAction
{
public void view()
{
//do view action
……
}
}
public class deleteAction
{
public void delete()
{
//do delete action
……
}
}
public class ModifyAction
{
public void modify()
{
//do modify action
……
}
}
我们可以看到,这样代码将各个行为独立出来,满足了单一职责原则,但这远远不够,因为它不满足依赖颠倒原则和里氏替换原则。
下面我们来看看命令模式对该问题的解决方法:
首先是定义一个接口:
public interface Action
{
public void doAction();
}
然后是各个实现:
public class AddAction implements Action
{
public void doAction()
{
//do add action
……
}
}
public class ViewAction implements Action
{
public void doAction()
{
//do view action
……
}
}
public class deleteAction implements Action
{
public void doAction()
{
//do delete action
……
}
}
public class ModifyAction implements Action
{
public void doAction()
{
//do modify action
……
}
}
这样,客户端的调用大概如下:
public void execute(Action action)
{
action.doAction();
}
看,上面的客户端代码再也没有出现过instanceof这样的语句,扩展性良好,也有了运行期内绑定的优点。
在这里,只拿出命令模式一个模式来作为例子来看看模式是怎么遵从里氏替换原则的!
发表评论
-
maven项目第一行报错:org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.mave
2020-04-09 01:23 519maven项目第一行报错:org.apache.maven.a ... -
删除项目中的所有.svn文件夹(或CVS文件夹)
2019-06-06 19:19 539当你的项目用SVN管理时,在项目的每个文件夹中会多一个.svn ... -
eclipse下生成Java类图和时序图,生成UML图
2016-12-30 02:28 2069最近老板让我做类图和时序图,提苦恼的,完全不会,就从网上整理 ... -
eclipse使用ModelGoon插件自动生成java类的UML图
2016-12-30 02:23 12491、ModelGoon介绍 ModelGo ... -
linux下的tomcat jvm内存
2016-11-30 23:19 597常见的内存溢出有以下两种: Java.lang.OutOf ... -
FTP实现客户端与服务器文件传输(二)
2016-08-06 01:22 1026/*以sun开头的class不是java里面的标准类,而是 ... -
java实现文件转换成二进制存储与取出
2016-08-06 01:21 2768一、功能描述: 将文件转成二进制数据放入数据库中,需要的 ... -
Resource specification not allowed here for source level below 1.7
2016-08-05 11:14 1193现象:tomcat能正常启动,但打开页面时,出现上面的错误 ... -
使用commons.net FTP 和sun.net.ftp.FtpClient 多种方式上传下载(包括批量)删除功能(一)
2016-08-04 10:38 690使用commons.net FTP 上传下载删除功能 ... -
第十一节 CAS服务端RememberMe
2016-06-07 11:03 1201关于启用RememberMe功能所需做的修改描述 ... -
第七节:CAS4.0.0 以上服务端配置多个数据源
2016-06-03 14:50 11431.首先打开deployerConfigContext.x ... -
第六节:CAS服务端自定义数据库认证用户
2016-06-03 11:46 2381/** * @see --------------- ... -
第四节:将CAS https的认证方式改为http
2016-06-01 08:49 1700一、CAS Server端的修改 1、找到cas\W ... -
java 读取html过滤标签
2016-05-27 16:19 1002public static void main(Strin ... -
获取cookie
2016-05-26 16:07 828获取cookie -
spring同时集成redis和mongodb时遇到多个资源文件加载的问题
2016-05-14 15:40 782两天平台中集成redis和mongodb遇到一个问题 单独 ... -
Windows上安装OpenSSL和生成证书
2016-05-10 15:52 24091,先下载OpenSSL http://www.slpr ... -
4.ubuntu14.04 安装mongodb笔记
2016-05-06 08:52 6781、使用系统自动获取安装。 1)获取更新 s ... -
3.nodejs nodejs的mysql模块
2016-04-12 22:20 594安装nodejs的mysql模块首先要选定一个数据库,我选择 ... -
第二节:cas处理中文乱码
2016-04-07 11:38 1344cas service配置参考第一节。 casServi ...
相关推荐
里氏替换原则由芭芭拉·利斯科夫教授于1987年提出,该原则的主要思想可以总结为:“所有引用基类的地方必须能透明地使用其子类的对象。”换句话说: 1. **替换性**:如果一个程序中的某个位置使用了基类对象,那么...
以上介绍的五种面向对象设计原则——单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则和开闭原则,都是面向对象编程领域中非常重要的指导思想。遵循这些原则可以帮助开发者构建出更加健壮、可维护和易于扩展...
这份名为“面向对象程序设计——入门”的资料,以PPT的形式,为初学者提供了一个系统的学习路径,涵盖了面向对象的基本概念、核心原则以及在Java语言中的实现方法。 1. **面向对象的基本概念** - **对象**:对象是...
除了这些基本概念,面向对象设计还涉及类的设计原则,如单一职责原则(Single Responsibility Principle, SRP)、开闭原则(Open-Closed Principle, OCP)、里氏替换原则(Liskov Substitution Principle, LSP)、...
面向对象设计原则也是设计模式的基础,包括单一职责原则(Single Responsibility Principle,SRP)、开闭原则(Open-Closed Principle,OCP)、里氏替换原则(Liskov Substitution Principle,LSP)、接口隔离原则...
3. 里氏替换原则:子类必须能够替换它们的父类并出现在父类能够出现的任何地方,而不影响程序的正确性。 4. 接口隔离原则:不应该强迫客户端依赖它们不需要的接口,应将一组相关的接口封装在一个单独的接口中。 5....
3. 里氏替换原则(Liskov Substitution Principle, LSP):子类型必须能够替换它们的基类型,并且在任何使用基类型的地方都能正常工作。 4. 接口隔离原则(Interface Segregation Principle, ISP):不应该强迫客户...
面向对象设计的五个基本原则,通常称为SOLID,是五个英文单词的首字母缩写:单一职责原则(Single Responsibility Principle, SRP)、开闭原则(Open/Closed Principle, OCP)、里氏替换原则(Liskov Substitution ...
- **设计模式原则**:包括单一职责原则、开闭原则、里氏替换原则等,用于指导设计模式的选择和使用。 #### 五、分层架构的重要性 **分层架构**: - **三层架构**:分为表现层、业务逻辑层和数据访问层,每一层都...
在实际项目中,结合面向对象的设计原则(如单一职责原则、开闭原则、里氏替换原则、依赖倒置原则等),我们可以构建出高效、高质量的软件系统。学习并熟练掌握这些设计模式,对于提升Java程序员的专业素养至关重要。
此外,面向对象设计原则,如SOLID原则(单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则),也是学习进阶的重要部分。遵循这些原则可以使代码更易于维护、扩展和测试。 总之,“C#面向对象练习...
设计原则如单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、依赖倒置原则(DIP)和接口隔离原则(ISP)等,可以帮助我们编写出更高质量的代码。同时,设计模式如工厂模式、单例模式、观察者模式等,是...
- **里氏替换原则**:子类对象应当能够替换掉它们的父类对象,而不影响程序的正确性。 - **依赖倒置原则**:高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象。 - **接口隔离原则**:客户端不应该被迫...
封装是面向对象编程的基础,它将数据和操作数据的方法绑定在一起,形成一个不可分割的整体——类(Class)。外部只能通过类提供的接口访问内部状态,这保护了数据的安全性和完整性。例如,在Java中,我们可以通过...
3. 里氏替换原则(Liskov Substitution Principle, LSP):子类型必须能够替换它们的基类型,而不影响程序的正确性。 4. 接口隔离原则(Interface Segregation Principle, ISP):客户端不应该被迫依赖它不需要的...
SOLID 是五个基本原则的首字母缩写,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)和依赖倒置原则(DIP)。遵循这些原则,可以使代码更易于理解和维护。 本在线培训学习...
学习Java面向对象编程不仅仅是掌握语法,更重要的是理解其设计理念和原则,如SOLID原则(单一职责、开闭、里氏替换、接口隔离、依赖倒置),以及设计模式的应用,如工厂模式、单例模式、观察者模式等。这些都将在...
11. SOLID原则:SOLID是面向对象设计的五个基本原则,包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则,它们指导开发者编写更灵活、可维护的代码。 12. 面向服务架构(SOA):虽然不完全是...
7. ** SOLID原则**:SOLID是面向对象设计的五个基本原则的首字母缩写,包括单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。书中可能会深入解析这些原则,并展示如何在实践中应用它们。 8....