常见 JavaScript 设计模式 — 原来这么简单(二)

简介: 常见 JavaScript 设计模式 — 原来这么简单

结构型设计模式

装饰器模式

核心是在不改变原 对象/方法 的基础上,通过对其进行包装拓展,使原有 对象/方法 可以满足更复杂的需求.

装饰器本质

装饰器模式本质上就是 函数的传参和调用,通过函数为已有 对象/方法 进行扩展,而不用修改原对象/方法,满足 开放封闭原则.

通过配置 babel 通过将 test.js 转为为 bable_test.js 用来查看装饰器的本质:

babel.config.json

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}
复制代码

test.js

// 定义装饰器
function decoratorTest(target) {
  console.log(target);
}
// 使用装饰器,装饰 Person 类
@decoratorTest
class Person {
  say() {}
  eat() {}
}
复制代码

执行 babel test.js --out-file babel_test.js 命令是生成 babel_test.js

"use strict";
var _class;
function decoratorTest(target) {
  console.log(target);
}
let Person = decoratorTest(_class = class Person {
  say() {}
  eat() {}
}) || _class;
复制代码

React 中的装饰器模式 —— HOC 高阶组件

高阶组件 是参数为 组件,返回值为新组件的 函数,在 ReactHOC 通常用于复用组件公共逻辑.

// TodoList 组件
class TodoList extends React.Component {}
// HOC 函数
function WrapContainer(Comp) {
  return (
    <div style={{ border: "1px solid red", padding: 10 }}>
      <Comp title="todo" />
    </div>
  );
}
// HOC 装饰 TodoList 组件,为 TodoList 组件包裹红色边框
const newTodoList = WrapContainer(TodoList);
复制代码

适配器模式

适配器模式本质就是 让原本不兼容的功能能够生效,避免大规模修改代码,对外提供统一使用.

Axios 中的适配器

通过观察 Axios 的目录结构,很容就发现其使用了适配器模式:

image.png

其实 Axios 中的 adapters 主要目的是根据当前运行时环境,向外返回对应的适配器 adapter,而这个适配器要做的其实就是兼容 web 浏览器环境和 node 环境的 http 请求,保证对外暴露的仍然是统一的 API 接口

代理模式

代理模式顾名思义就是 不能直接访问目标对象,需要通过代理器来实现访问,通常是为了提升性能、保证安全等.

事件代理

事件代理是很常见的性能优化手段之一,react 的事件机制也采用了事件代理的方式(篇幅有限可自行了解),这里演示简单的 JavaScript 事件代理:

<div id="container">
  <p>this number is 1</p>
  <p>this number is 2</p>
  <p>this number is 3</p>
  <p>this number is 4</p>
  <p>this number is 5</p>
</div>
<script>
  const container = document.querySelector("#container");
  container.addEventListener("click", function (e) {
    alert(e.target.textContent);
  });
</script>
复制代码

Vue 中的代理 Proxy

Vue.js 3 中通过 Proxy 实现了对数据的代理,任何读取、设置的操作都会被 代理对象handlers 拦截到,从而实现 Vue 中的 tracktrigger

image.png

image.png

行为型设计模式

策略模式

策略模式实际上就是定义一系列的算法,将单个功能封装起来,并且对扩展开放.

举个例子

假如我们需要为某个游乐场的门票价格做差异化询价,主要人员类型分为 儿童、成年人、老年人 三种,其对应的门票折扣为 8折、9折、8.5折

if-else 代码一把梭

缺点:无论哪种人员类型的折扣变动,都需要修改 finalPrice 函数,不符合对 对修改封闭

function finalPrice(type, price) {
  if (type === "child") {
    // do other thing
    return price * 0.8;
  }
  if (type === "adult") {
    // do other thing
    return price * 0.9;
  }
  if (type === "aged") {
    // do other thing
    return price * 0.85;
  }
}
复制代码

单一功能封装

缺点:若人员类型增加妇女类型,仍然需要修改 finalPrice 函数,且不符合 对扩展开放

function childPrice(price) {
  // do other thing
  return price * 0.8;
}
function adultPrice(price) {
  // do other thing
  return price * 0.9;
}
function agedPrice(price) {
  // do other thing
  return price * 0.85;
}
function finalPrice(type, price) {
  if (type === "child") {
    return childPrice(price);
  }
  if (type === "adult") {
    return adultPrice(price);
  }
  if (type === "aged") {
    return agedPrice(price);
  }
}
复制代码

创建映射关系

通过映射关系,很好的将 finalPrice 和 具体的计算逻辑进行分离,在需要扩展类型时,只需要修改 priceTypeMap 对象而不用修改对外暴露的 finalPrice 函数.

const priceTypeMap = {
  child: function (price) {
    // do other thing
    return price * 0.8;
  },
  adult: function (price) {
    // do other thing
    return price * 0.9;
  },
  aged: function (price) {
    // do other thing
    return price * 0.85;
  },
};
function finalPrice(type, price) {
    return priceTypeMap[type](price);
}


目录
相关文章
|
4月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 职责链模式
js设计模式【详解】—— 职责链模式
76 8
|
4月前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 组合模式
js设计模式【详解】—— 组合模式
52 7
|
1月前
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
30 3
|
3月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
50 1
|
3月前
|
设计模式 JavaScript 前端开发
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
|
4月前
|
设计模式 JavaScript Go
js设计模式【详解】—— 状态模式
js设计模式【详解】—— 状态模式
79 7
|
4月前
|
设计模式 JavaScript
js设计模式【详解】—— 桥接模式
js设计模式【详解】—— 桥接模式
67 6
|
4月前
|
设计模式 JavaScript
js设计模式【详解】—— 原型模式
js设计模式【详解】—— 原型模式
49 6
|
4月前
|
设计模式 JavaScript 算法
js设计模式【详解】—— 模板方法模式
js设计模式【详解】—— 模板方法模式
47 6
|
4月前
|
设计模式 存储 JavaScript
js设计模式【详解】—— 享元模式
js设计模式【详解】—— 享元模式
64 6