博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式6大原则:里氏置换原则
阅读量:6838 次
发布时间:2019-06-26

本文共 3366 字,大约阅读时间需要 11 分钟。

hot3.png

1. 里氏替换原则

里式替换原则(Liskov Substitution Principle,LSP),所有引用基类的地方必须能够透明的使用其子类对象。也就是说,只要父类出现的地方都能替换为子类,不会产生异常。但是反过来,子类出现的地方,替换为父类就可能出现问题。 也就是子类可以扩展父类的功能,但不能改变父类的功能。 通俗的讲:类需要扩展功能时,新类继承旧类,使用新类替换旧类不会造成故障。 

1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法; 
2. 子类中可以增加自己持有的方法; 
3. 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松; 
4. 当子类的方法实现父类的抽象方法是,方法的后置条件(即方法的返回值)要比父类更严格。

2. 单一职责原则

单一职责原则(Single Responsibility Principle, SRP), 

There should never be more than one reason for a class to change. (应该有且仅有一个原因引起类的变更) 
以下摘自: 
有时候,开发人员设计接口的时候,将用户的属性和用户的行为放在一个接口中声明。这就造成业务对象和业务逻辑放在一起了。 
例子:

public interface Itutu {
   //height    void setHeight(double height);    void getHeight();    //weight    void setWeight(double weight);    void getWeight();    //eat    void eat(boolean hungry);    //surf in internet    void internet(boolean buy);}

单一职责的意义 

1. 降低类的复杂性,实现什么样的职责都有清晰的定义; 
2. 提高可读性和可维护性; 
3. 降低变更引起的风险,对系统扩展性和维护性很有帮助。

3. 依赖倒置原则

依赖倒置原则(Dependency Inversion Principle, DIP) 

Definition: High level modules should not depend upon low level modules, Both should depend upon abstractions. Abstractions should not depend upon details, details should depend upon abstractions.

即:高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。

抽象:即抽象类或接口,是不能够实例化的。

细节:即具体的实现类,实现接口或者继承抽象类所产生的类,可以通过关键字new直接被实例化。

每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。

面向接口编程 

以下摘自

讲了这么多,估计大家对“倒置”这个词还是有点不理解,那到底什么是“倒置”呢?我们先说“正置”是什么意思,依赖正置就是类间的依赖是实实在在的实现类间的依赖,也就是面向实现编程,这也是正常人的思维方式,我要开奔驰车就依赖奔驰车,我要使用笔记本电脑就直接依赖笔记本电脑,而编写程序需要的是对现实世界的事物进行抽象,抽象的结果就是有了抽象类和接口,然后我们根据系统设计的需要产生了抽象间的依赖,代替了人们传统思维中的事物间的依赖,“倒置”就是从这里产生的。

依赖倒转原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合,我们怎么在项目中使用这个规则呢?只要遵循以下的几个规则就可以:

每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备。 

这是依赖倒置的基本要求,接口和抽象类都是属于抽象的,有了抽象才可能依赖倒置。

变量的显示类型尽量是接口或者是抽象类。 

很多书上说变量的类型一定要是接口或者是抽象类,这个有点绝对化了,比如一个工具类,xxxUtils一般是不需要接口或是抽象类的。还有,如果你要使用类的clone方法,就必须使用实现类,这个是JDK提供一个规范。

任何类都不应该从具体类派生。 

如果一个项目处于开发状态,确实不应该有从具体类派生出的子类的情况,但这也不是绝对的,因为人都是会犯错误的,有时设计缺陷是在所难免的,因此只要不超过两层的继承都是可以忍受的。特别是做项目维护的同志,基本上可以不考虑这个规则,为什么?维护工作基本上都是做扩展开发,修复行为,通过一个继承关系,覆写一个方法就可以修正一个很大的Bug,何必再要去继承最高的基类呢?

尽量不要覆写基类的方法。 

如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会产生一定的影响。

4. 开闭原则

抽象层确定后不再修改。通过抽象层导出多个新的具体类实现扩展。

5. 接口隔离原则

客户端不应该不依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上。使用多个专门的接口比使用单一的总接口要好。 

一个类对另外一个类的依赖性应当是建立在最小的接口上的。 
一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。 
“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”这个说得很明白了,再通俗点说,不要强迫客户使用它们不用的方法,如果强迫用户使用它们不使用的方法,那么这些客户就会面临由于这些不使用的方法的改变所带来的改变。

接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;而接口隔离原则主要约束接口接口,主要针对抽象,针对程序整体框架的构建。

采用接口隔离原则对接口进行约束时,要注意以下几点:

接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。 

为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。 
提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。 
运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。

6. 迪米特法则

也称为最少知识原则(LeastKnowledge Principle, LKP): 一个软件实体应当尽可能少的与其他实体发生相互作用。当一个模块发生修改时,尽量少地影响其他模块。

迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类: 

(1) 当前对象本身(this); 
(2) 以参数形式传入到当前对象方法中的对象; 
(3) 当前对象的成员对象; 
(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友; 
(5) 当前对象所创建的对象。

转载于:https://my.oschina.net/u/2505806/blog/529673

你可能感兴趣的文章
推荐一些工具类网站
查看>>
Visual Paradigm 教程[UML]:如何在序列图中应用消息编号?
查看>>
iOS自定义简易刷新视图(仿MJRefresh)
查看>>
你需要知道的Android View的布局
查看>>
vuex源码分析
查看>>
用vue优雅地编写UI组件的几条指导原则
查看>>
关于element-ui 中使用Notice组件(Message、MessageBox、Notification)所遇到的坑
查看>>
常用命令
查看>>
「译」在JavaScript中将值转换为字符串的5种方法
查看>>
Java maven的 pom.xml配置文件中使用全局变量配置版本号
查看>>
从dropbox的使用引申想到的系统集成
查看>>
安装 kubernetes-dashboard
查看>>
mysql主从同步主服务器热切换
查看>>
解决wget下载中文乱码的方法
查看>>
简单的说一说java线程中的死锁和嵌套管程锁死问题?
查看>>
[Spark][翻译]Spark 架构: Shuffle过程分析
查看>>
CentOS 7安装fail2ban+Firewalld防止SSH爆破
查看>>
git常用操作命令
查看>>
sendmail邮件服务器支持账户名大小写
查看>>
深入浅出WPF开发下载
查看>>