博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 设计模式 -- 其他模式
阅读量:3950 次
发布时间:2019-05-24

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

JavaScript 设计模式----其他模式

1. 其他模式

1.1 创建型

1.1.1 原型模式
  • 概念
    • clone 自己,生成一个对象
    • java 默认有 clone 接口,不用自己实现
  • JS 中的应用 - Object.create
// `Object.create` 用到了原型模式的思想(虽然不是 java 中的 clone)// 基于一个原型创建一个对象var prototype = {
getName: function () {
return this.first + ' ' + this.last }, say: function () {
console.log('hello') }}// 基于原型创建 xvar x = Object.create(prototype)x.first = 'A'x.last = 'B'console.log(x.getName())x.say()// 基于原型创建 yvar y = Object.create(prototype)y.first = 'C'y.last = 'D'console.log(y.getName())y.say()
  • 对比 JS 中的原型 prototype
    • prototype 可以理解为 ES6 class 的一种底层原理
    • class 是实现面向对象的基础,并不是服务于某个模式
    • 若干年后 ES6 全面普及,大家可能会忽略掉 prototype
    • 但是 Object.create 却会长久存在

1.2 结构型

1.2.1 桥接模式
  • 概念
    • 用于把抽象化与实现化解耦
    • 使得二者可以独立变化
  • 演示
    在这里插入图片描述
  • 代码实现
class ColorShape {
yellowCircle() {
console.log('yellow circle') } redCircle() {
console.log('red circle') } yellowTriangle() {
console.log('yellow triangle') } redTriangle() {
console.log('red triangle') }}// 测试let cs = new ColorShape()cs.yellowCircle()cs.redCircle()cs.yellowTriangle()cs.redTriangle()
  • 演示
    在这里插入图片描述
  • 代码演示
class Color {
constructor(name) {
this.name = name }}class Shape {
constructor(name, color) {
this.name = name this.color = color } draw() {
console.log(`$[this.color.name} ${
this.name}`) }}// 测试let red = new Color('red')let yellow = new Color('yellow')let circle = new Shape('circle', red)circle.draw()let triangle = new Shape('triangle', yellow)triangle.draw()
  • 设计原则验证
    • 抽象和实现分离,解耦
    • 符合开放封闭原则
1.2.2 组合模式
  • 概念
    • 生成树形结构,表示“整体-部分”关系
    • 让整体和部分都具有一致的操作方式
  • 示例
    在这里插入图片描述
  • 演示
    • JS 经典应用中,未找到这么复杂的数据类型
    • 虚拟 DOM 中的 vnode 是这种形式,但数据类型简单
    • 用 JS 实现一个菜单,不算经典应用,与业务相关

123

456

{
tag: 'div', attr: {
id: 'div1', className: 'container' }, children: [ {
tag: 'p', attr: {
}, children: ['123'] }, {
tag: 'p', attr: {
}, children: ['456'] } ]}
  • 演示
    • 整体和单个节点的操作是一致的
    • 整体和单个节点的数据结构也保持一致
  • 设计原则验证
    • 将整体和单个节点的操作抽象出来
    • 符合开放封闭原则
1.2.3 享元模式
  • 概念
    • 共享内存(主要考虑内存,而非效率)
    • 相同的数据,共享使用
  • 演示
  • 设计原则验证
    • 将相同的部分抽象出来
    • 符合开放封闭原则
1.2.4 外观模式
  • 概念
    • 为子系统中的一组接口提供了一个高层接口
    • 使用者使用这个高层接口
  • 示例
    • 去医院看病,接待员去挂号】门诊、划价、取药

在这里插入图片描述

  • UML 类图
    在这里插入图片描述
  • 场景
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector selector = null }// ******}// 调用bindEvent(elem, 'click', '#div1', fn)bindEvent(elem, 'click', fn)
  • 设计原则验证
    • 不符合单一职责原则和开放封闭原则,因此谨慎使用,不可滥用

1.3 行为型

1.3.1 策略模式
  • 概念
    • 不同策略分开处理
    • 避免出现大量 if...else 或者 switch...case
  • 演示
class User {
constructor(type) {
this.type = type } buy() {
if (this.type === 'ordinary') {
console.log('普通用户购买') } else if (this.type === 'member') {
console.log('会员用户购买') } else if (this.type === 'vip') {
console.log('vip 用户购买') } }}// 测试代码var u1 = new User('ordinary')u1.buy()var u2 = new User('member')u2.buy()var u3 = new User('vip')u3.buy()
class OrdinaryUser {
buy() {
console.log('普通用户购买') }}class MemberUser {
buy() {
console.log('会员用户购买') }}class VipUser {
buy() {
console.log('vip 用户购买') }}var u1 = new OrdinaryUser()u1.buy()var u2 = new MemberUser()u2.buy()var u3 = new VipUser()u3.buy()
  • 设计原则验证
    • 不同策略,分开处理,而不是混合在一起
    • 符合开放封闭原则
1.3.2 模版方法模式
class Action {
handle() {
handle1() handle2() handle3() } handle1() {
console.log('1') } handle2() {
console.log('2') } handle3() {
console.log('3') }}
1.3.3 职责链模式
  • 概念
    • 一步操作可能分位多个职责角色来完成
    • 把这些角色都分开,然后用一个链串起来
    • 将发起者和各个处理者进行隔离
  • 演示
// 请假审批,需要组长审批、经理审批、最后总监审批class Action {
constructor(name) {
this.name = name this.nextAction = null } setNextAction(action) {
this.nextAction = action } handle() {
console.log(`${
this.name} 审批`) if (this.nextAction != null) {
this.nextAction.handle() } }}let a1 = new Action('组长')let a2 = new Action('经理')let a3 = new Action('总监')a1.setNextAction(a2)a2.setNextAction(a3)a1.handle()
  • JS 中的链式操作
    • 职责链模式和业务结合较多,JS 中能联想到链式操作
    • jQuery 的链式操作 Promise.then 的链式操作
  • 设计原则验证
    • 发起者于各个处理者进行隔离
    • 符合开放封闭原则
1.3.4 命令模式
  • 概念
    • 执行命令时,发布者和执行者分开
    • 中间加入命令对象,作为中转站
  • 示例
    在这里插入图片描述
  • 演示
// 接收者class Receiver {
exec() {
console.log('执行') }}// 命令者class Command {
constructor(receiver) {
this.receiver = receiver } cmd() {
console.log('触发命令') this.receiver.exec() }}// 触发者class Invoker {
constructor(command) {
this.command = command } invoke() {
console.log('开始') this.command.cmd() }}// 士兵let soldier = new Receiver()// 小号手let trumpeter = new Command(soldier)// 将军let general = new Invoker(trumpeter)general.invoke()
  • JS 中的应用
    • 网页富文本编辑器操作,浏览器封装了一个命令对象
    • document.execCommand('bold')
    • document.execCommand('undo')
  • 设计原则验证
    • 命令对象于执行对象分开,解耦
    • 符合开放封闭原则
1.3.5 备忘录模式
  • 概念
    • 随时记录一个对象的状态变化
    • 随时可以恢复之前的某个状态(如撤销功能)
    • 未找到 JS 中经典应用,除了一些工具(如编辑器)
  • 演示
// 状态备忘class Memento {
constructor(content) {
this.content = content } getContent() {
return this.content }}// 备忘列表class CareTaker {
constructor() {
this.list = [] } add(memento) {
this.list.push(memento) } get(index) {
return this.list[index] }}// 编辑器class Editor {
constuctor() {
this.content = null } setContent(content) {
this.content = content } getContent() {
return this.content } saveContentToMemento() {
// 创建备忘实例 return new Memento(this.content) } getContentFromMemento(memento) {
this.content = memento.getContent() }}// 测试代码let editor = new Editor()let careTaker = new CareTaker()editor.setContent('111')editor.setContent('222')careTaker.add(editor.saveContentToMemento()) // 存储备忘录editor.setContent('333')careTaker.add(editor.saveContentToMemento()) // 存储备忘录editor.setContent('444')console.log(editor.getContent())editor.getContentFromMemento(careTaker.get(1)) // 撤销console.log(editor.getContent())editor.getContentFromMemento(careTaker.get(0)) // 撤销console.log(editor.getContent())
  • 设计原则验证
    • 状态对象于使用者分开,解耦
    • 符合开放封闭原则
1.3.6 中介者模式
  • 概念
    在这里插入图片描述
  • 演示
// 中介者class Mediator {
constructor(a, b) {
this.a = a this.b = b } setA() {
let number = this.b.number this.a.setNumber(number * 100) } setB() {
let number = this.a.number this.b.setNumber(number / 100) }}class A {
constructor() {
this.number = 0 } setNumber(num, m) {
this.number = num if (m) {
m.setB() } }}class B {
constructor() {
this.number = 0 } setNumber(num, m) {
this.number = num if (m) {
m.setA() } }}// 测试let a = new A()let b = new B()let m = new Mediator(a, b)a.setNumber(100)console.log(a.number, b.number)b.setNumber(100)console.log(a.number, b.number)
  • 设计原则验证
    • 讲各关联对象通过中介者隔离
    • 符合开放封闭原则
1.3.7 访问者模式
  • 概念
    • 将数据操作和数据结构进行分离
    • 使用场景不多
1.3.8 解释器模式
  • 概念
    • 描述语言语法如何定义,如何解释和编译
    • 用于专业场景

转载地址:http://wjqwi.baihongyu.com/

你可能感兴趣的文章
Dealing with Audio Output Hardware 处理音频输出硬件设备
查看>>
Monitoring the Battery Level and Charging State 监测电池电量和充电状态
查看>>
Determining and Monitoring the Docking State and Type 判断并监测设备的停驻状态与类型
查看>>
Determining and Monitoring the Connectivity Status 根据网络连接状况去省电
查看>>
Manipulating Broadcast Receivers On Demand 按需操控广播接收
查看>>
Creating a View Class 创建一个视图类
查看>>
Custom Drawing 自定义绘制
查看>>
Making the View Interactive 视图互动
查看>>
Optimizing the View 优化视图
查看>>
Setting Up the Search Interface 设置搜索界面
查看>>
Storing and Searching for Data 数据存储和搜索
查看>>
Remaining Backward Compatible 保持向后兼容
查看>>
Remembering Your User 记住你的用户
查看>>
Authenticating to OAuth2 Services 验证OAuth2服务
查看>>
Creating a Custom Account Type 创建自定义帐户类型
查看>>
Sending Content to Other Apps 将内容发送到其他应用程序
查看>>
Receiving Content from Other Apps 接收来自其他应用程序的内容
查看>>
Adding an Easy Share Action 添加一个简单的共享行动
查看>>
Taking Photos Simply 简单地拍摄照片
查看>>
Recording Videos Simply 简单录制视频
查看>>