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直接被实例化
JavaScript 设计模式的七大原则(未完成)的更多相关文章
- java设计模式之七大原则
java设计模式 以下内容为本人的学习笔记,如需要转载,请声明原文链接 https://www.cnblogs.com/lyh1024/p/16724932.html 设计模式 1.设计模式的目的 ...
- 设计模式的七大原则(Java)
一.OOP三大基本特性 OOP 面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法.模型是用来反映现实世 ...
- JavaScript设计模式之设计原则
何为设计 即按照哪一种思路或者标准来实现功能,功能相同,可以有不同的设计方案来实现 伴随着需求的增加,设计的作用就会体现出来,一般的APP每天都在变化,更新很快,需求不断在增加,如果设计的不好,后面很 ...
- Java设计模式_七大原则
简介 单一职责原则.对类来说,即一个类应该只负责一项职责. 开闭原则.对扩展开放,对修改关闭.在程序需要进行扩展的时候,不能去修改原有代码,使用接口和抽象类实现一个热插拔的效果. 里氏替换原则.任何基 ...
- 设计模式七大原则(C++描述)
前言 最近在学习一些基本的设计模式,发现很多博客都是写了六个原则,但我认为有7个原则,并且我认为在编码中思想还是挺重要,所以写下一篇博客来总结下 之后有机会会写下一些设计模式的博客(咕咕咕...... ...
- Java设计模式(1:软件架构设计七大原则及开闭原则详解)
前言 在日常工作中,我们使用Java语言进行业务开发的时候,或多或少的都会涉及到设计模式,而运用好设计模式对于我而言,又是一个比较大的难题.为了解决.克服这个难题,笔主特别开了这个博客来记录自己学习的 ...
- JavaScript设计模式导学
如何成为一名合格的工程师? 作为一名合格的工程师,不仅需要懂代码,还要懂设计,一名合格工程师的必备条件: 前端开发有一定的设计能力,一般三年开发经验的同学,面试必须考设计能力 成为项目技术负责人,设计 ...
- Java设计模式遵循的七大原则
最近几年来,人们踊跃的提倡和使用设计模式,其根本原因就是为了实现代码的复用性,增加代码的可维护性.设计模式的实现遵循了一些原则,从而达到代码的复用性及增加可维护性的目的,设计模式对理解面向对象的三大特 ...
- 【设计模式系列】之OO面向对象设计七大原则
1 概述 本章叙述面向向对象设计的七大原则,七大原则分为:单一职责原则.开闭原则.里氏替换原则.依赖倒置原则.接口隔离原则.合成/聚合复用原则.迪米特法则. 2 七大OO面向对象设计 2.1 单一 ...
随机推荐
- 运行pytorch代码遇到的error解决办法
1.no CUDA-capable device is detected 首先考虑的是cuda的驱动问题,查看gpu显示是否正常,然后更新最新的cuda驱动: 第二个考虑的是cuda设备的默认参数是否 ...
- 《linux就该这么学》第四节课笔记,三章和四章开始!
第三章 (根据课本和在线培训视频排版总结,借鉴请改动) 右键可打开终端练习 3.1:输入输出重定向 输入重定向:符号 "<" ,是一种 ...
- ORA-00907: 缺失右括号,原因及解决办法整理
ORA-00907: 缺失右括号,原因及解决办法整理 1 union all中order by 导致缺失右括号 在有union all的子查询中使用了order by,会导致缺失右括号的错误,事实上在 ...
- Lua论分析需求(学好英文)的重要性
题目是这样的: Observe that its base and height are both equal to , and the image is drawn using # symbols ...
- Spring Cloud配置中心(Config)
Spring Cloud配置中心(Config) Spring Cloud是现在流行的分布式服务框架,它提供了很多有用的组件.比如:配置中心.Eureka服务发现. 消息总线.熔断机制等. 配置中心在 ...
- 16款优秀的Vue UI组件库推荐
16款优秀的Vue UI组件库推荐 Vue 是一个轻巧.高性能.可组件化的MVVM库,API简洁明了,上手快.从Vue推出以来,得到众多Web开发者的认可.在公司的Web前端项目开发中,多个项目采用基 ...
- Shell 实践、常用脚本
(1)计算1-100的和. #!/bin/bash n= ` do n=$[$i+$n] done echo $n (2)输一个数字,然后计算出1到数字的和,要求如果输入数字小于1,则重新输入,知道输 ...
- Linux 默认线程栈大小 调优
Linux 线程栈介绍 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区.里面的变量通常是局部变量.函数参数等:和堆相比,栈通常很小. Linux 查询线程栈 1.查看默认的 ...
- ssm回顾笔记(一)
这两天来到了农银,这边即将进行的一个项目是将ssh框架的电商项目迁移到springboot+ssm框架上,所以我基本上是三门技术在同时进行学习,当然以前学过ssm,现在只是回顾. spring 注解 ...
- 由 UWP 版网易云音乐闪退引发的博文
今天,不知怎么的.网易云音乐出现了一打开就闪退的情况.百度了好些时候未果,就直接 Windows + i 打开 Windows 设置 > 应用 在应用和功能列表中找到网易云音乐,在展开的 高级选 ...