JavaScript 设计模式的七大原则(未完成)
设计模式(面向对象)有七大设计原则,分别是:
开闭原则:对扩展开放,对修改关闭
单一职责原则:每一个类应该专注于做一件事情
里氏替换原则:父类存在的地方,子类是可以替换的
依赖倒转原则:实现尽量依赖抽象,不依赖具体实现
接口隔离原则
合成服用原则
迪米特法原则
一、开闭原则
开闭原则是面向对象设计中最基础的设计原则。
对扩展开放:这意味着模块的行为是可以扩展的。当应用的需求改变时,可以对模块进行扩展,使其具有新的功能满足需求的变化。
对修改关闭:不允许对实体做任何修改,就是这些需要执行多样行为的实体应该设计成不需要修改就可以实现各种的变化,坚持开闭原则有利于用最少的代码进行项目维护。
举个栗子
需求:商品列表中,如果是男装类型,商品背景色使用蓝色 ,点击之后弹出男装价格;如果是女装,商品背景色使用红色,点击后弹出女装品牌。
以下为代码示范:
普通代码我们会这么做:
// 渲染html的函数中if (commodity.type === '男装') {commodity.css(background, blue);} else {commodity.css(background, red);}// 点击事件的函数中if (commodity.type === '男装') {// 弹出价格 alert(commodity.price);} else {// 弹出品牌 alert(commodity.brand);}
看起来一切都很好,代码上线了。过了一阵,PM告知添加一种商品类型,童装,商品背景色使用黄色,点击之后弹出童装的销量。
那么,代码会被改成下面这样:
// 渲染html的函数中if (commodity.type === '男装') {commodity.css(background, blue);} else if (commodity.type === '女装') { // 修改点1 增加女装类型判断 commodity.css(background, red);} else { // 修改点2 增加童装html渲染处理 commodity.css(background, yellow);}// 点击事件的函数中if (commodity.type === '男装') {// 弹出价格 alert(commodity.price);} else if (commodity.type === '女装') { // 修改点3 增加女装类型判断// 弹出价格 alert(commodity.brand);} else { // 修改点4 增加童装点击处理// 弹出销量 alert(commodity.sales);}
ok,以上是可能的代码编写方式,当需求发生变化时,会对原有代码很多地方进行修改,因为修改的地方过于琐碎,修改后。心里一定会慌慌的,同时修改过程也好火眼金睛,生怕漏掉某一处代码,代码可想而知。
下面我们看一下符合开闭原则的代码:
// getManager的实现 function getManager(commodity) {if (commodity.type === '男装') return MaleManager;if (commodity.type === '女装') return FemaleManager;}let MaleManager = {Settingbackground: function () {commodity.css(background, blue);},Prompt: function () {// 弹出价格 alert(commodity.price);}};let FemaleManager = {Settingbackground: function () {commodity.css(background, red);},Prompt: function () {// 弹出品牌 alert(commodity.brand);}};
ok,代码量好像多了,多了好几个对象和方法。。。我们接着往下看,当需求发生了变化,童装出现的时候,代码如下:
// getManager的实现 function getManager(commodity) {if (commodity.type === '男装') return MaleManager;if (commodity.type === '女装') return FemaleManager;if (commodity.type === '童装') return ChildManager; // 修改点1 添加童装管理器的路由,此处可以利用约定的方式而不用修改,后面再讲 }let MaleManager = {Settingbackground: function () {commodity.css(background, blue);},Prompt: function () {// 弹出价格 alert(commodity.price);}};let FemaleManager = {Settingbackground: function () {commodity.css(background, red);},Prompt: function () {// 弹出品牌 alert(commodity.brand);}};// 修改点2 添加童装管理器,此处其实不算修改,是新增一个对象let ChildManager = {Settingbackground: function () {commodity.css(background, yellow);},Prompt: function () {// 弹出销量 alert(commodity.sales);}};
我们可以看到,按照开闭原则设计后的代码,修改点只有一处,修改的地方也可以预判,修改路由方法getManager即可(此处修改其实可以避免);然后新增一个童装manager即可。
二、单一职责原则
就一个类而言,应该仅有一个引起它变化的原因。
我们在做编程的时候,很自然的会在一个类上加上各种各样的功能。这意味着,无论任何需求要来,只需要修改这个类,这样其实是糟糕的,维护麻烦,复用不可能。单一职责就是每个类型功能要求单一,一个类只负责干一件事,类的可读性提高,复杂度降低;可读性提高了,代码就更容易维护;变更(需求是肯定会变的,程序员都知道)引起的风险(包括测试的难度,以及需要测试的范围)降低。
举一个最普通的例子,比如我们写一个最简单的静态页,我们就会创建一个js文件,一个css文件,一个images文件,我们会把对应的文件类型放到对应的文件夹下面。如果我们需要修改样式,我们就会去css文件夹下面去找需要修改样式的对应css文件,比如我们想添加一张图片我们就会去images文件下去放一张需要添加的图片。这样下来我们进行代码修改或添加的时候也会比较方便,节省开发时间。
代码:
<input type="text" id="ipt"><script>var ipt = document.getElementById('ipt')ipt.onclick = function () {console.log('这是鼠标点击事件!')}ipt.ondblclick = function () {console.log('这是鼠标双击事件!')}ipt.onmouseover = function () {console.log('这是鼠标移入事件!')}ipt.onmouseout = function () {console.log('这是鼠标移出事件!')}ipt.onblur = function () {console.log('这是失去焦点事件!')}ipt.keydown = function () {console.log('这是键盘按下事件!')}ipt.keyup = function () {console.log('这是键盘抬起事件!')}</script>
比如上面代码,每个事件只执行每个事件对应的代码。
那么单一职责原则的意义何在呢?
- 降低类的复杂性,实现什么样的职责都有清晰的定义
- 提高可读性
- 提高可维护性
- 降低变更引起的风险,对系统扩展性和维护性很有帮助
三、里氏替换原则
通俗的定义:所有引用基类的地方必须能透明地使用其子类的对象。
更通俗的定义:子类可以扩展父类的功能,但不能改变父类原有的功能。
里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,而且功能不受影响时,基类才能真正被复用,而衍生类也能在子类的基础上增加新的功能。(也就是说,任何一个子类的实例都可以替换父类的实例,而功能不受影响)
要遵循里氏替换原则, 需要保证子类在实现父类方法时,必须遵循父类的方法,而且不能重写父类已经定义的方法,可以这样理解继承中父类的关系:
父类中定义的方法,实际上是在设定一系列的规则和契约,虽然它不强制子类必须遵循这些契约,但是如果子类对父类的方法修改,就会对整个继承体系产生破坏。
子类必须完全实现父类的方法
里氏替换原则定义了什么是父子,还有一点要注意的,就是儿子不能在父亲会的技能上搞“创新”。
比如父亲会做红烧排骨,儿子在新东方烹饪学校中学到了一招,在红烧排骨里面加糖和醋,变成红烧糖醋排骨,更加美味,看代码,儿子在父亲的基础红烧排骨上加了糖醋,好像没啥问题。
class Father1 {braisedRibs() {console.log("红烧排骨");}}class Son1 extends Father1 {braisedRibs() {console.log("红烧糖醋排骨");}}
运行下面代码,会打印:红烧排骨。
var Father = new Father1();Father.braisedRibs()
在使用父亲的地方,都能够替换成儿子,并且效果是一样的,那接下来我们改一下代码。
var BigSon = new Son1();Son.braisedRibs()
结果是啥?打印出:红烧糖醋排骨。 父亲会的东西儿子必须继承下来,在父亲不在的时候儿子必须能顶上,但是儿子不能忘掉继承下来的东西,也不能把继承下来的东西修改成别的,这就不遵循里氏替换。
子类可以有自己的个性
我们来看一下父亲的小儿子,小儿子也在新东方烹饪学校学了个手艺。
class Son2 extends Father1 {braisedSweetAndSourPorkRibs() {console.log("红烧甜汤排骨");}}
测试一下是不是好儿子
var SmallSon = new Son2();SmallSonn.braisedRibs()SmallSonn.braisedSweetAndSourPorkRibs()
打印出:
红烧排骨 红烧糖醋排骨
这才是 父亲 的好儿子嘛,不仅会红烧排骨,还会红烧糖醋排骨。所以说里氏替换原则就是在定义父子关系,大家都遵守这个定义,就会一代比一代好,不遵守大家也看到了,把前辈传下来的都毁于一旦了。
四、依赖倒转原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象
抽象:即抽象类或接口,两者是不能够实例化的
细节:即具体的实现类,实现接口或者继承抽象类所产生的类,两者可以通过关键字new直接被实例化
转载于:https://www.cnblogs.com/Mr-Tao/p/10423618.html
JavaScript 设计模式的七大原则(未完成)相关推荐
- 代码规范七大原则_设计模式的七大原则详解||上篇
Hello 丨World 当机会变得稀有,当竞争变得激烈 当方向不再清晰,当风口不再有风 关键词||设计模式 全文约7685字,细读大约需要20分钟 1 认识设计模式 1.1 什么是设计模式 所谓设 ...
- 依赖倒转原则_Java设计模式的七大原则
Java设计模式的七大原则 里氏代换原则 里氏代换原则是对"开-闭"原则的补充.实现"开-闭"原则的关键步骤就是抽象化.而基类与子类的继承关系就是抽象化的具体实 ...
- JAVA设计模式的七大原则
设计模式的目的: 1)代码重用性(相同功能的代码,不用多次编写) 2)可读性(编程规范性,使代码易于阅读和理解) 3)可拓展性(也称作可维护性,当需要增加功能时,十分方便) 4)可靠性(增加新的功能后 ...
- 03【设计模式的七大原则】
文章目录 三.设计模式的七大原则 3.1 单一职责原则 3.1.1 介绍 3.1.2 应用示例 3.2 接口隔离原则 3.2.1 介绍 3.2.2 应用示例: 3.2.3 案例优化: 3.3 开闭原则 ...
- 设计模式开路先锋 | 七大原则
目录 设计模式 概念 目的 设计模式的七大原则 单一职责原则(Single Responsibility Principle) 接口隔离原则(Interface Segregation Princip ...
- 最详细的设计模式的七大原则讲解
精心整理了设计模式的七大原则,包括代码解释方便理解,但是难免不了存在纰漏,感谢大家的指正与理解!觉的写的不错的小伙伴儿,一键三连支持一下,后期会有持续更新!!抱拳了罒ω罒 设计模式的七大原则 面向对象 ...
- 设计模式笔记-----七大原则
一,设计模式的目的 提高代码重用性,可读性,可扩展性,可靠性,使程序具有低耦合高内聚的特征 二,七大原则 1.单一职责原则 2.接口隔离原则 3.依赖倒置原则 4.里欧替换原则 5.开闭原则 6.迪米 ...
- 面试官问你如何进行程序设计?——设计模式之七大原则——接口隔离、合成复用、迪米特法则以及C++设计实现
设计模式的设计原则之2.0 七大原则 5.接口隔离(InterfaceSegregation Principle,ISP) 5.1.背景 5.2.定义 5.3.特征 5.4.应用 6.迪米特原则(La ...
- 【设计模式】设计模式的七大原则
设计模式原则 设计模式原则,其实就是程序员在编程时,应当遵守的原则, 也是各种设计模式的基础(即:设计模式为什么这样设计的依据) 设计模式常用的七大原则有: 单一职责原则 接口隔离原则 依赖倒转(倒置 ...
最新文章
- R语言使用ggplot2包的快速可视化函数qplot绘制基础密度图实战
- 想拥有最新的微软嵌入式技术 就赶快加入微软嵌入式专家社区吧!
- 拦截器获取请求参数post_SpringBoot拦截器如何获取http请求参数
- 程序猿果真有前端后端client吗
- linux文件属性是什么意思,Linux文件属性
- mysql 主备XtraBackup恢复
- 修改Android中strings.xml文件, 动态改变数据
- [VB]用记录集填充表格函数
- 京东购物车双11实战
- 【渝粤教育】电大中专跨境电子商务理论与实务 (30)作业 题库
- [渝粤题库] 国家开放大学 人文英语4 资料
- then是java关键字吗_then是java关键字吗
- 基于遗传算法优化极限学习机预测及其MATLAB实现-附代码
- 离散LQR与iLQR的推导思路
- ICM40607 六轴传感器简介和配置
- 关于最近阿里内部员工抢月饼事件引发的js程序扩展
- 苹果手机升级后开不了机怎么办_iPhone8突然黑屏开不了机怎么办?西安苹果售后维修点教你这样解决...
- Qt ui 到底是什么?
- UVM基本介绍(UVM class hierarchy、验证平台、树状图)
- .net core word转pdf_Enolsoft PDF to Word with OCR for Mac(PDF转Word软件)
热门文章
- 机器学习工程师需要具备的5种软技能
- FACEGOOD 推出10万点人脸关键点跟踪,重新定义工业级人脸3D重建
- 麻省理工学院开发出可“听音识貌”的人工智能
- 你真的了解AI吗?AI将怎么改变我们的生活?
- 「情报局41」人工智能的下一个目标是什么?了解业务用例
- “一束光”让机器人也能拥有触觉?之江实验室这项技术惊艳世界
- 用跑得最慢的电脑程序,理解最高深的哥德巴赫猜想
- 城市大脑,是工程问题,但首先是基础科学问题
- Gartner:2020 年 AI 平台魔力象限:意外多多
- 垃圾要分类!我们的大脑如何处理垃圾呢?