本文已参与[新人创作礼]活动,一起开启掘金创作之路。
设计模式是什么?
假设有一个空房间,我们要日复一日地往里面放一些东西。最简单的办法当然是把这些东西 直接扔进去,但是时间久了,就会发现很难从这 个房子里找到自己想要的东西,要调整某几样东 西的位置也不容易。所以在房间里做一些柜子也许是个更好的选择,虽然柜子会增加我们的成 本,但它可以在维护阶段为我们带来好处。使用 这些柜子存放东西的规则,就是一种模式。
学习设计模式,有助于写出可复用和可维护性高的程序。
其实我们在开发的过程中可能很少会用到设计模式,因为很多东西别人都帮我们封装好了,我们直接拿过来用即可。但是技多不压身,毕竟还要防一手面试呀!
设计模式中常用的都有哪些模式呢?
- 单例模式
- 装饰模式
- 观察者模式
- 组合模式
其他的就不一一举例了,如果想要深入了解的话,可以到下面的链接里看看噢!
zhuanlan.zhihu.com/p/114011162
JavaScript设计模式_林夏天的博客-CSDN博客_js设计模式 阮一峰
设计模式综合案例:小米家具
本案例主要是在浏览器的控制台输出结果哈,所以效果要通过结合代码和控制台来观察!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn1">外反锁</button>
<button id="btn2">关灯</button>
<!--
·全局共有5件小米智能家居:小米控制台、小米门禁、小米电灯、小米电视;
·从外反锁门=>全屋进入【外出模式】=>所有电器自动断电
·电灯关闭10分钟=>全屋自动进入【睡眠模式】=>电视关闭+空调进入微风状态+门禁内反锁;
-->
<!-- 设计模式底层架构 -->
<script>
/* 小米家居基类 */
class MiDevice {
constructor(name) {
this.name = name
}
powerOn() {
console.log(this.name, "powerOn");
}
powerOff() {
console.log(this.name, "powerOff");
}
}
/* 事件源=被观察者(Observable) */
class DataSource extends MiDevice {
constructor(name) {
super(name)
this.listeners = []
this.value = null
}
// 添加观察者
addListener(...listeners) {
this.listeners.push(...listeners)
}
// 注销观察者
removeListener(listener) {
this.listeners = this.listeners.filter(
li => li !== listener
)
}
// 发布事件(通知所有观察者响应)
publishEvent(event) {
this.listeners.forEach(
li => li.onEvent(event)
)
}
}
/* 观察者:只要有onEvent(event)方法就是观察者(无论是否显式地继承Observer) */
class Observer extends MiDevice {
onEvent(event) {
console.log(this.name, "onEvent", event);
}
}
/* 组合 */
class Compose extends MiDevice {
constructor(name) {
super(name)
this.components = []
}
// 添加组件
addComponent(component) {
this.components.push(component)
}
// 注销组件
removeComponent(component) {
for (let i = 0; i < this.components.length; i++) {
if (this.components[i] === component) {
this.components.splice(i, 1)
break
}
}
}
// 下达号令
platformSwitchMode(mode) {
// 让所有组件都响应号令
this.components.forEach(
c => c.switchMode(mode)
)
}
}
/* 组件: 只要有switchMode(mode)方法就可算是组件(无论是否显式地继承Component) */
class Component extends MiDevice {
switchMode(mode) { }
}
</script>
<!-- 家居类封装 -->
<script>
/* 小爱同学 */
class MiControl extends /* Observer */Compose {
static mode = {
modeAbsent: "外出模式",
modeSleep: "睡眠模式"
}
static singleton = null
static getSingleton() {
!this.singleton && (this.singleton = new MiControl)
return this.singleton
}
constructor() {
super("小爱同学")
}
/* 作为观察者响应事件 */
/* 我已经有onEvent了 所以我已经是观察者了 无需一定要继承Observer */
onEvent(event) {
// super.onEvent(event)
console.log(this.name, "onEvent", event);
switch (event.type) {
/* 处理门禁事件 */
case MiDoor.eventType:
if (event.value === MiDoor.mode.lockFromOutside) {
// 命令所有组件进入【外出模式】
this.platformSwitchMode(MiControl.mode.modeAbsent)
}
break;
/* 处理灯具事件 */
case MiLight.eventType:
if (event.value === MiLight.mode.sleep) {
// 命令所有组件进入【外出模式】
this.platformSwitchMode(MiControl.mode.modeSleep)
}
break;
default:
break;
}
}
}
class MiDoor extends DataSource {
static eventType = "MiDoor"
static mode = {
open: "open",
closed: "closed",
lockFromInside: "lockFromInside",
lockFromOutside: "lockFromOutside"
}
constructor() {
super("小米门禁")
}
handle(mode) {
console.log(this.name, mode);
/* 作为事件源主动发布事件 */
this.publishEvent({
type: MiDoor.eventType,
value: mode
})
}
switchMode(mode) {
console.log(this.name, "switchMode", mode);
switch (mode) {
case MiControl.mode.modeSleep:
this.handle(MiDoor.mode.lockFromInside)
break;
default:
break;
}
}
}
class MiLight extends /* Component */DataSource {
static eventType = "MiLight"
static mode = {
sleep: "睡眠模式",
ktv: "劲舞模式",
candleMeal: "烛光晚餐模式",
}
constructor() {
super("MiLight")
}
switchMode(mode) {
switch (mode) {
// 外出模式
case MiControl.mode.modeAbsent:
this.powerOff()
break;
default:
break;
}
}
powerOff() {
super.powerOff()
setTimeout(
() => {
this.publishEvent({
type: MiLight.eventType,
value: MiLight.mode.sleep
})
},
3000
)
}
}
class MiTV extends Component {
constructor() {
super("MiTV")
}
switchMode(mode) {
switch (mode) {
// 外出模式
case MiControl.mode.modeAbsent:
this.powerOff()
break;
// 睡眠模式
case MiControl.mode.modeSleep:
this.sleep()
break;
default:
break;
}
}
sleep() {
console.log(this.name, "正在静默下载您喜爱的老师的片子...");
}
}
</script>
<!-- 业务逻辑 -->
<script>
const mcontrol = MiControl.getSingleton()
const mdoor = new MiDoor()
const mlight = new MiLight()
const mtv = new MiTV()
// 小米门禁(事件源)添加小爱同学作为观察者
mdoor.addListener(mcontrol)
mlight.addListener(mcontrol)
/* 所有设备都归小爱同学统一号令 */
mcontrol.addComponent(mdoor)
mcontrol.addComponent(mlight)
mcontrol.addComponent(mtv)
/* 反锁门 */
btn1.onclick = function (e) {
mdoor.handle(MiDoor.mode.lockFromOutside)
}
/* 关灯 */
btn2.onclick = function (e) {
mlight.powerOff()
}
</script>
</body>
</html>