面向对象的七大原则
Posted yishifuping
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象的七大原则相关的知识,希望对你有一定的参考价值。
面向对象七大原则(丢了一个合成复用)
单一原则:
单一原则,只得就是,所有的类,文件,接口... 单一,一个文件,一个类,一个文件,只干这一件事
遵循单一职责原的优点有:
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
开闭原则:
原理:对修改关闭,对扩展开放
基类的子扩展。
例子:element时间组件的使用
<div class="block"> <span class="demonstration">日期:</span> <el-date-picker v-model="timeSpan" type="daterange" :picker-options="pickerOptions2" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" align="right"> </el-date-picker> </div> <script> export default { data() { return { // 时间范围选择 pickerOptions2: { shortcuts: [ { text: "最近一周", onClick(picker) { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); picker.$emit("pick", [start, end]); } }, { text: "最近一个月", onClick(picker) { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); picker.$emit("pick", [start, end]); } }, { text: "最近三个月", onClick(picker) { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); picker.$emit("pick", [start, end]); } } ], } } } </script>
原因:软件系统的功能上的可扩展性要求模块是扩展开放的,软件系统的功能上的稳定性,持续性要求是修改关闭的。根本控制需求变动风险,缩小维护成本。
核心:用抽象构建框架,用实现类实现扩展,在不修改原有模块的基础上能扩展其功能。
优点: 增加稳定性、可扩展性高。
里氏替换:
子类能够替换父类,出现在父类能够出现的任何地方,子类必须完全实现父类的方法。在类中调用其他类是务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了原则。覆盖或实现父类的方法时输入参数可以被放大。即子类可以重载父类的方法,但输入参数不比父类方法中的小,这样在子类代替父类的时候,调用的仍然是父类的方法。里氏替换原则是针对继承而言的,如果继承是为了实现代码重用,也就是为了共享方法,那么共享的方法应该保持不变,不被子类重新定义。如果继承是为了多态那么,而多态的前提是子类覆盖父类的方法所以将父类定义为抽象类,抽象类不能够实例化对象也就不存在替换这一说。
子类可以扩展父类的功能,但不能改变父类原有的功能
继承机制的优点:
代码共享,减少创建类的工作量
提高代码的重用性;
子类可以形似父类,又异于父类;
提高父类的扩展性,实现父类的方法即可随意而为;
继承机制的缺点:
继承是入侵性的(只要继承,就必须拥有父类的所有属性与方法);
降低了代码的灵活性(子类拥有了父类的属性方法,会增多约束);
增强了耦合性(当父类的常量、变量、方法被修改时,必需要考虑子类的修改)。
class Shape { constructor() { this.ant=‘蚁群‘ } } class Rectangle extends Shape { constructor() { super(); this.ant=‘蚁后‘ this.action=‘啥也不干‘ } setactions(dance) { this.action=dance } getArea() { return this.ant + this.action; } } class Square extends Shape { constructor() { super(); this.ant=‘蚁后‘ this.action=‘啥也不干‘ } setaction(high) { this.action = high; } getArea() { return this.ant + this.action; } } function renderLargeShapes(shapes) { shapes.forEach((shape) => { console.log(shape) switch (shape.constructor.name) { case ‘Square‘: shape.setaction(‘跳高‘); break; case ‘Rectangle‘: shape.setactions(‘跳舞‘); break; } let area = shape.getArea(); console.log(area) }) } let shapes = [new Rectangle(), new Square()]; renderLargeShapes(shapes);
依赖倒转原则:
我的理解:以前的依赖都是单对单的,当你修改其中一个将影响到下一的东西的使用。依赖倒转的原则就是,多对多的原则,由以前两层模式,更改成现在的三层模式,上层,依赖抽象层,在连接到下层。
上层的马,牛,鸡,都依赖于跑的这个抽象类,下层的跑的方式同样依赖于中层的抽象层。
上层的每一项都可以去调用到下层的每一项(多对多的关系),当想添加上层事物,或添加下层的方式,都不会影响到其他的事件,能够快速的的进行开发,减少更改代码的周期。
以上是我的理解
以下是系统解释:
依赖倒置原则的优点
可以通过抽象使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合(也是本质)
可以规避一些非技术因素引起的问题(项目大时,需求变化的概率也越大,通过采用依赖倒置原则设计的接口或抽象类对实现类进行约束,可以减少需求变化引起的工作量剧增情况。同时,发生人员变动,只要文档完善,也可让维护人员轻松地扩展和维护)
可以促进并行开发(如,两个类之间有依赖关系,只要制定出两者之间的接口(或抽象类)就可以独立开发了,规范已经定好了,而且项目之间的单元测试也可以独立地运行,而TDD开发模式更是DIP的最高级应用(特别适合项目人员整体水平较低时使用))
1. 模块间的依赖通过抽象类或接口发生,实现类之间的依赖关系也是通过抽象类或接口产生(实现类之间不应发生直接的依赖关系),降低系统的耦合性
2. 接口或抽象不依赖于实现类,但实现类依赖接口或抽象类,实现类对系统需要的功能具体实现,提高类的内聚程度
上段代码,来理解下,不知道我理解的对不对了
<html> <head></head> <body> </body> <script> class Shape { constructor() { this.ant=‘蚁群‘ } } class sheep { constructor() { this.ant=‘羊群‘ } } class Rectangle extends Shape { constructor() { super(); this.ant=‘蚁后‘ this.action=‘啥也不干‘ } getArea() { return this.ant + this.action; } } class Square extends sheep { constructor() { super(); this.ant=‘羊群‘ this.action=‘吃草‘ } getArea() { return this.ant + this.action; } } function renderLargeShapes(shapes) { shapes.forEach((shape) => { console.log(shape) switch (shape.constructor.name) { case ‘Square‘: break; case ‘Rectangle‘:; break; } let area = shape.getArea(); console.log(area) }) } let shapes = [new Rectangle(), new Square()]; renderLargeShapes(shapes); </script> </html>
接口隔离:
1、官方定义
接口隔离原则,英文缩写ISP,全称Interface Segregation Principle。
原始定义:Clients should not be forced to depend upon interfaces that they don’t use,还有一种定义是The dependency of one class to another one should depend on the smallest possible interface。
官方翻译:其一是不应该强行要求客户端依赖于它们不用的接口;其二是类之间的依赖应该建立在最小的接口上面。简单点说,客户端需要什么功能,就提供什么接口,对于客户端不需要的接口不应该强行要求其依赖;类之间的依赖应该建立在最小的接口上面,这里最小的粒度取决于单一职责原则的划分。
接口隔离原则和单一职责原则
从功能上来看,接口隔离和单一职责两个原则具有一定的相似性。其实如果我们仔细想想还是有区别的。
(1)从原则约束的侧重点来说,接口隔离原则更关注的是接口依赖程度的隔离,更加关注接口的“高内聚”;而单一职责原则更加注重的是接口职责的划分。
(2)从接口的细化程度来说,单一职责原则对接口的划分更加精细,而接口隔离原则注重的是相同功能的接口的隔离。接口隔离里面的最小接口有时可以是多个单一职责的公共接口。
(3)单一职责原则更加偏向对业务的约束,接口隔离原则更加偏向设计架构的约束。这个应该好理解,职责是根据业务功能来划分的,所以单一原则更加偏向业务;而接口隔离更多是为了“高内聚”,偏向架构的设计。
以上官方定义
以下自己理解:
我认为,接口隔离,就是把以前的一个接口调3,4个东西,完咯给分割一下,把多个东西拆成安区域,功能区分割一下它。如图
没有进行隔离的图样:一个事件,把所有的都给调出来了
经过隔离后的样事:简单分离下(但不符合单一原则)
其实我感觉吧,当你使用了 单一原则后,你所谓的接口隔离原则,好像就没有什么用了,毕竟单一原则上面讲了,一个接口调用一件事,就不存在一调多了
里米特法则:
以上是关于面向对象的七大原则的主要内容,如果未能解决你的问题,请参考以下文章