Skip to content

1.1 写在前面:为什么要学设计模式?

你好,欢迎来到 JavaScript 设计模式学习手册!

在正式开始学习之前,你可能会有一个疑问:“我写的 JavaScript 代码运行得好好的,为什么还要多此一举,去学什么‘设计模式’呢?”

这是一个非常好的问题。学习任何新知识之前,我们都应该先明确它的价值。这篇文章将通过一个你可能非常熟悉的场景,带你一步步感受设计模式的魅力,并解答这个核心问题。

一、你是否也写过这样的代码?

假设我们正在开发一个系统,需要根据用户的不同角色(admin, editor, viewer)来决定他们能访问哪些页面。很多人的第一反应可能就是写一连串的 if...else 或者 switch 语句。

场景:根据用户角色判断页面访问权限

javascript
function checkAccess(role, page) {
  if (role === "admin") {
    // 管理员拥有所有权限
    return true;
  } else if (role === "editor") {
    // 编辑可以访问内容管理和统计页面
    if (page === "content-management" || page === "dashboard") {
      return true;
    } else {
      return false;
    }
  } else if (role === "viewer") {
    // 访客只能访问统计页面
    if (page === "dashboard") {
      return true;
    } else {
      return false;
    }
  } else {
    // 其他未知角色,一律拒绝
    return false;
  }
}

// 使用
console.log(checkAccess("editor", "content-management")); // true
console.log(checkAccess("viewer", "content-management")); // false

这段代码能工作吗?当然可以。但它“好”吗?让我们来审视一下它的问题:

  • 难以阅读和维护:随着角色和判断逻辑的增多,这个函数会变得越来越长,嵌套越来越深,像一个巨大的“面条怪兽”。
  • 违反“开放/封闭原则”:如果未来需要增加一个新的角色,比如 contributor(贡献者),我们必须修改 checkAccess 函数内部的代码。在复杂的系统中,频繁修改核心函数是非常危险的,容易引发新的 bug。
  • 复用性差:如果另一个地方也需要类似的权限判断,但逻辑略有不同,我们很难复用这里的代码,很可能需要复制粘贴,然后进行修改。

当你的项目越来越大,这种代码会成为你的噩梦。那么,有没有更好的方法呢?

二、代码的“套路”:设计模式登场

想象一下,我们做菜有“菜谱”,下棋有“棋谱”,习武有“秘籍”。这些“谱”和“秘籍”都是前人总结出来的、在特定场景下解决特定问题的最佳实践通用“套路”

在软件工程领域,同样存在这样的“套路”,它就是 设计模式 (Design Pattern)

设计模式是在软件设计过程中,针对特定问题,经过验证的、可复用的解决方案。它不是一个具体的类或库,而是一种思想和方法论。

学习设计模式,就像是站在巨人的肩膀上,用一种更优雅、更高效的方式来组织你的代码,去解决那些反复出现的“老问题”。

三、小试牛刀:用“模式”优化代码

让我们看看,如果用一种叫做 “策略模式” (Strategy Pattern) 的设计思想来重构上面的权限判断代码,会是什么样子。

提示

你现在不需要完全理解下面的代码是如何工作的。这里的目的只是让你直观地感受一下代码结构上的变化。我们会在后续的章节中详细学习它。

javascript
// 1. 定义不同角色的策略(处理逻辑)
const strategies = {
  admin: function (page) {
    return true;
  },
  editor: function (page) {
    return page === "content-management" || page === "dashboard";
  },
  viewer: function (page) {
    return page === "dashboard";
  },
  // 默认策略
  default: function (page) {
    return false;
  },
};

// 2. 创建一个统一的检查函数
function checkAccess(role, page) {
  // 根据角色名,找到对应的策略函数,如果找不到就用默认的
  const strategy = strategies[role] || strategies.default;
  return strategy(page);
}

// 使用方式完全一样!
console.log(checkAccess("editor", "content-management")); // true
console.log(checkAccess("viewer", "content-management")); // false

// 新增一个角色,变得无比轻松!
strategies.contributor = function (page) {
  return page === "contribution-page" || page === "dashboard";
};
console.log(checkAccess("contributor", "contribution-page")); // true

对比一下,你发现了什么?

  • 结构清晰:每个角色的逻辑都被封装在自己的函数里,一目了然。
  • 易于扩展:新增 contributor 角色时,我们没有修改原来的 checkAccess 函数,只是增加了一个新的策略。这完全符合“开放/封闭原则”。
  • 可维护性高:修改某个角色的权限,只需要找到对应的策略函数即可,不会影响到其他逻辑。

我们仅仅是换了一种“套路”,代码的质量就得到了质的飞跃。这就是设计模式的力量!

四、学习设计模式,你将收获什么?

  • 🚀 提升代码质量:写出更易于维护、扩展和复用的代码,告别“面条代码”。
  • 🗣️ 建立通用语言:当你和同事说“这里可以用策略模式”,他们能立刻明白你的意图。这大大提高了团队沟通的效率。
  • 🧠 锻炼工程思维:学习模式会让你从更高的维度去思考问题,而不仅仅是实现功能。你会开始考虑代码的灵活性、健壮性和未来的可能性。
  • 🏆 助力职业发展:无论是面试还是实际工作,熟练运用设计模式都是中高级工程师的重要标志。

五、准备好了吗?

本手册将以最适合初学者的方式,用通俗易懂的语言和贴近实际的 JavaScript 案例,带你一步步探索设计模式的世界。

我们不会去死记硬背概念,而是去理解每个模式背后所解决的问题和蕴含的思想。

现在,收起你的疑虑,让我们一起踏上这段激动人心的“代码修行”之旅吧!