在前端、Node.js 项目开发中,创建型模式负责对象实例化、结构型模式负责类与对象组合,而行为型模式聚焦对象之间的通信、算法、职责流转、状态管理等业务行为逻辑。合理使用行为型模式可以拆分复杂业务流程、降低对象间耦合、统一调度规则,大幅提升代码可扩展性与可读性。

23 种经典设计模式中,行为型模式共 11 种:模板方法、策略、观察者、迭代器、责任链、命令、备忘录、中介者、状态、访问者、解释器。本文采用标准技术博客文风,每种模式包含模式介绍、适用场景、优缺点、规范 TypeScript 代码实现,所有代码严格遵循统一编码格式规范:常量全大写下划线、函数大写下划线命名、运算符前后空格、{ 尾随行尾、} 独占一行、if 判断常量左置、所有代码块强制大括号。

一、模板方法模式

模式介绍

定义一套固定不变的算法骨架,将流程中可变步骤抽象为抽象方法,交由子类实现。父类控制整体执行顺序,子类仅重写差异化逻辑,符合开闭原则。

适用场景

  1. 多业务流程整体步骤一致,仅局部逻辑不同;
  2. 需要统一约束执行流程,防止子类篡改整体执行顺序。

优缺点

优点:流程统一管控、代码复用、扩展简单;缺点:抽象类耦合子类,流程变更需要修改父类。

const PRINT_PREFIX = "执行流程:";

abstract class Game_Template {
    // 固定流程骨架
    public Run_Game(): void {
        this.Init_Game();
        this.Start_Match();
        this.End_Match();
    }

    protected abstract Init_Game(): void;
    protected abstract Start_Match(): void;

    // 通用固定逻辑
    protected End_Match(): void {
        console.log(`${PRINT_PREFIX}对局结束,结算分数`);
    }
}

class King_Game extends Game_Template {
    protected Init_Game(): void {
        console.log(`${PRINT_PREFIX}王者荣耀加载地图与英雄资源`);
    }

    protected Start_Match(): void {
        console.log(`${PRINT_PREFIX}5v5峡谷对战开启`);
    }
}

class FPS_Game extends Game_Template {
    protected Init_Game(): void {
        console.log(`${PRINT_PREFIX}射击游戏加载枪械与地图资源`);
    }

    protected Start_Match(): void {
        console.log(`${PRINT_PREFIX}多人枪战模式开启`);
    }
}

// 测试调用
let king: Game_Template = new King_Game();
king.Run_Game();
console.log("----------");
let fps: Game_Template = new FPS_Game();
fps.Run_Game();

二、策略模式

模式介绍

将一组独立算法封装为策略类,统一实现相同接口,外部持有策略对象动态切换,消除大量 if/else、switch 判断。

适用场景

  1. 同一业务存在多种分支算法,需要频繁切换;
  2. 复杂多分支判断,希望拆分逻辑、提升可维护性。

优缺点

优点:消除分支判断、算法独立扩展、符合单一职责;缺点:策略类数量增多,需要统一管理策略。

interface Pay_Strategy {
    Get_Discount(price: number): number;
}

class Vip_Pay implements Pay_Strategy {
    public Get_Discount(price: number): number {
        return price * 0.8;
    }
}

class Normal_Pay implements Pay_Strategy {
    public Get_Discount(price: number): number {
        return price;
    }
}

class Pay_Context {
    private strategy: Pay_Strategy;

    constructor(strategy: Pay_Strategy) {
        this.strategy = strategy;
    }

    public Set_Strategy(strategy: Pay_Strategy): void {
        this.strategy = strategy;
    }

    public Calc_Price(origin: number): number {
        return this.strategy.Get_Discount(origin);
    }
}

// 测试调用
const ORIGIN_PRICE = 100;
let context = new Pay_Context(new Normal_Pay());
console.log("普通用户价格:", context.Calc_Price(ORIGIN_PRICE));

context.Set_Strategy(new Vip_Pay());
console.log("VIP用户价格:", context.Calc_Price(ORIGIN_PRICE));

三、观察者模式(发布订阅)

模式介绍

定义一对多依赖关系,当目标对象状态变更时,自动通知所有订阅观察者,实现发布者与订阅者解耦。

适用场景

  1. 事件通知、消息推送、状态监听;
  2. UI 数据联动、聊天室消息广播、全局状态变更。

优缺点

优点:发布订阅完全解耦、支持动态增减监听;缺点:消息广播无筛选,大量观察者会造成性能损耗。

interface Observer {
    Update_Msg(msg: string): void;
}

class User_Observer implements Observer {
    private user_name: string;

    constructor(name: string) {
        this.user_name = name;
    }

    public Update_Msg(msg: string): void {
        console.log(`${this.user_name} 收到消息:${msg}`);
    }
}

class Subject_Publish {
    private observer_list: Observer[] = [];

    public Add_Observer(observer: Observer): void {
        this.observer_list.push(observer);
    }

    public Remove_Observer(target: Observer): void {
        let index = this.observer_list.indexOf(target);
        if (-1 != index) {
            this.observer_list.splice(index, 1);
        }
    }

    public Notify_All(msg: string): void {
        for (let i = 0; i < this.observer_list.length; i++) {
            this.observer_list[i].Update_Msg(msg);
        }
    }
}

// 测试调用
let publish = new Subject_Publish();
let user1 = new User_Observer("用户A");
let user2 = new User_Observer("用户B");

publish.Add_Observer(user1);
publish.Add_Observer(user2);
publish.Notify_All("服务器开启全员活动");

四、迭代器模式

模式介绍

提供统一遍历接口,隔离集合内部存储结构,客户端无需关心底层数组、链表、树形结构,统一方式遍历元素。

适用场景

  1. 多种数据结构需要统一遍历逻辑;
  2. 希望隐藏集合内部实现,对外只暴露遍历能力。

优缺点

优点:遍历与集合解耦、统一遍历规范;缺点:额外新增迭代器类,增加代码量。

interface Iterator_Interface {
    Has_Next(): boolean;
    Next(): string | null;
}

class Array_Iterator implements Iterator_Interface {
    private data_list: string[];
    private index: number = 0;

    constructor(list: string[]) {
        this.data_list = list;
    }

    public Has_Next(): boolean {
        return this.index < this.data_list.length;
    }

    public Next(): string | null {
        if (this.Has_Next()) {
            let val = this.data_list[this.index];
            this.index = this.index + 1;
            return val;
        }
        return null;
    }
}

class Data_Collection {
    private data: string[] = ["苹果", "香蕉", "橙子"];

    public Get_Iterator(): Iterator_Interface {
        return new Array_Iterator(this.data);
    }
}

// 测试调用
let collection = new Data_Collection();
let it = collection.Get_Iterator();
while (true == it.Has_Next()) {
    console.log(it.Next());
}

五、责任链模式

模式介绍

将多个处理节点串联成一条链路,请求依次传递,每个节点可选择处理请求或传递给下一级,实现请求发送与处理解耦。

适用场景

  1. 多级校验:权限校验、参数校验、登录校验;
  2. 日志分级打印、异常逐级捕获、审批流程。

优缺点

优点:灵活调整处理链路、新增处理器不修改原有代码;缺点:请求可能无人处理,链路过长影响性能。

abstract class Check_Handler {
    protected next_handler: Check_Handler | null = null;

    public Set_Next(handler: Check_Handler): void {
        this.next_handler = handler;
    }

    public abstract Check_Data(param: number): boolean;
}

class Login_Check extends Check_Handler {
    public Check_Data(param: number): boolean {
        if (param < 1) {
            console.log("登录校验失败");
            return false;
        }
        if (null != this.next_handler) {
            return this.next_handler.Check_Data(param);
        }
        return true;
    }
}

class Auth_Check extends Check_Handler {
    public Check_Data(param: number): boolean {
        if (param < 10) {
            console.log("权限校验失败");
            return false;
        }
        if (null != this.next_handler) {
            return this.next_handler.Check_Data(param);
        }
        return true;
    }
}

// 测试调用
let login = new Login_Check();
let auth = new Auth_Check();
login.Set_Next(auth);

const TEST_PARAM = 12;
if (true == login.Check_Data(TEST_PARAM)) {
    console.log("全部校验通过");
}

六、命令模式

模式介绍

将请求封装为独立命令对象,包含执行、撤销方法,实现请求发送者与执行者解耦,支持命令队列、撤销、重做。

适用场景

  1. 按钮点击、菜单操作、批量任务队列;
  2. 需要记录操作、回滚撤销操作的场景。

优缺点

优点:命令可存储、排队、撤销;解耦调用与执行;缺点:每一种操作都要新建命令类。

interface Command_Interface {
    Execute(): void;
    Undo(): void;
}

class Light_Device {
    public Turn_On(): void {
        console.log("灯光打开");
    }

    public Turn_Off(): void {
        console.log("灯光关闭");
    }
}

class Light_On_Command implements Command_Interface {
    private device: Light_Device;

    constructor(dev: Light_Device) {
        this.device = dev;
    }

    public Execute(): void {
        this.device.Turn_On();
    }

    public Undo(): void {
        this.device.Turn_Off();
    }
}

class Controller_Invoker {
    private command: Command_Interface;

    constructor(cmd: Command_Interface) {
        this.command = cmd;
    }

    public Trigger(): void {
        this.command.Execute();
    }

    public Revoke(): void {
        this.command.Undo();
    }
}

// 测试调用
let light = new Light_Device();
let cmd = new Light_On_Command(light);
let controller = new Controller_Invoker(cmd);
controller.Trigger();
controller.Revoke();

七、备忘录模式

模式介绍

在不破坏对象封装的前提下,保存对象内部状态,支持随时恢复历史状态,快照备份。

适用场景

  1. 编辑器撤销回退、游戏存档、表单草稿保存;
  2. 需要记录对象历史快照,且不暴露内部字段。

优缺点

优点:状态备份与恢复简单、隔离对象内部数据;缺点:大量快照会占用内存。

class Editor_Memento {
    private text_content: string;

    constructor(content: string) {
        this.text_content = content;
    }

    public Get_Content(): string {
        return this.text_content;
    }
}

class Text_Editor {
    private content: string = "";

    public Write_Text(str: string): void {
        this.content = str;
    }

    public Save_Snapshot(): Editor_Memento {
        return new Editor_Memento(this.content);
    }

    public Restore(memo: Editor_Memento): void {
        this.content = memo.Get_Content();
    }

    public Show_Text(): void {
        console.log("当前文本:", this.content);
    }
}

// 测试调用
let editor = new Text_Editor();
editor.Write_Text("第一段文字");
let snapshot = editor.Save_Snapshot();
editor.Show_Text();

editor.Write_Text("修改后的文字");
editor.Show_Text();

editor.Restore(snapshot);
editor.Show_Text();

八、中介者模式

模式介绍

引入中介者统一管理多个对象交互,所有对象通信仅通过中介转发,消除多对象之间的复杂多对多依赖。

适用场景

  1. 聊天室多用户消息互通、组件联动、多模块交互;
  2. 对象互相依赖,依赖关系杂乱难以维护。

优缺点

优点:简化对象依赖关系、集中管理交互逻辑;缺点:中介者逻辑过重,过于庞大难以维护。

abstract class Chat_User {
    protected user_name: string;
    protected mediator: Chat_Mediator | null = null;

    constructor(name: string) {
        this.user_name = name;
    }

    public Set_Mediator(m: Chat_Mediator): void {
        this.mediator = m;
    }

    public abstract Send_Msg(msg: string): void;
    public abstract Receive_Msg(from: string, msg: string): void;
}

class Chat_Mediator {
    private user_list: Chat_User[] = [];

    public Register_User(user: Chat_User): void {
        this.user_list.push(user);
        user.Set_Mediator(this);
    }

    public Forward_Msg(sender: Chat_User, msg: string): void {
        for (let i = 0; i < this.user_list.length; i++) {
            let target = this.user_list[i];
            if (target != sender) {
                target.Receive_Msg(sender.user_name, msg);
            }
        }
    }
}

class Normal_User extends Chat_User {
    public Send_Msg(msg: string): void {
        if (null != this.mediator) {
            this.mediator.Forward_Msg(this, msg);
        }
    }

    public Receive_Msg(from: string, msg: string): void {
        console.log(`${this.user_name} 收到 ${from} 的消息:${msg}`);
    }
}

// 测试调用
let mediator = new Chat_Mediator();
let u1 = new Normal_User("小明");
let u2 = new Normal_User("小红");
mediator.Register_User(u1);
mediator.Register_User(u2);
u1.Send_Msg("大家好");

九、状态模式

模式介绍

对象行为随内部状态改变而变化,将每种状态独立封装为状态类,切换状态即可切换对象行为,消除大量状态判断分支。

适用场景

  1. 订单状态、设备开关机、审批流转、游戏角色状态;
  2. 对象行为高度依赖自身状态,状态分支繁多。

优缺点

优点:状态逻辑拆分、新增状态无需修改原有代码;缺点:状态类数量较多。

interface Order_State {
    Handle_Operate(): void;
}

class Wait_Pay_State implements Order_State {
    public Handle_Operate(): void {
        console.log("订单待支付,可发起付款");
    }
}

class Already_Pay_State implements Order_State {
    public Handle_Operate(): void {
        console.log("订单已支付,等待发货");
    }
}

class Order_Context {
    private state: Order_State;

    constructor(init_state: Order_State) {
        this.state = init_state;
    }

    public Set_State(new_state: Order_State): void {
        this.state = new_state;
    }

    public Do_Operate(): void {
        this.state.Handle_Operate();
    }
}

// 测试调用
let wait_pay = new Wait_Pay_State();
let paid = new Already_Pay_State();
let order = new Order_Context(wait_pay);
order.Do_Operate();
order.Set_State(paid);
order.Do_Operate();

十、访问者模式

模式介绍

分离数据结构与数据操作,新增操作无需修改元素类,通过访问者扩展元素行为,适合稳定数据结构、频繁新增操作的场景。

适用场景

  1. 报表统计、文件目录多种导出格式、统一数据多维度计算;
  2. 对象结构固定,经常需要新增不同操作逻辑。

优缺点

优点:新增操作简单、操作逻辑集中;缺点:修改元素结构会改动所有访问者。

interface Visitor {
    Visit_Text(el: Text_Element): void;
    Visit_Img(el: Img_Element): void;
}

abstract class Doc_Element {
    public abstract Accept(visitor: Visitor): void;
}

class Text_Element extends Doc_Element {
    public Accept(visitor: Visitor): void {
        visitor.Visit_Text(this);
    }
}

class Img_Element extends Doc_Element {
    public Accept(visitor: Visitor): void {
        visitor.Visit_Img(this);
    }
}

class Export_Pdf_Visitor implements Visitor {
    public Visit_Text(el: Text_Element): void {
        console.log("将文本导出为PDF格式");
    }

    public Visit_Img(el: Img_Element): void {
        console.log("将图片导出为PDF格式");
    }
}

// 测试调用
let text = new Text_Element();
let img = new Img_Element();
let pdf_visitor = new Export_Pdf_Visitor();
text.Accept(pdf_visitor);
img.Accept(pdf_visitor);

十一、解释器模式

模式介绍

定义语法表达式,构建语法树解析自定义规则,用于解析小型自定义语法、表达式规则。

适用场景

  1. 自定义表达式引擎、简单规则脚本、正则简易解析;
  2. 系统存在小型可自定义语法规则。

优缺点

优点:语法规则易扩展、分层清晰;缺点:复杂语法类爆炸,性能较差。

interface Expression {
    Interpret(): number;
}

class Num_Expression implements Expression {
    private num: number;

    constructor(n: number) {
        this.num = n;
    }

    public Interpret(): number {
        return this.num;
    }
}

class Add_Expression implements Expression {
    private left: Expression;
    private right: Expression;

    constructor(l: Expression, r: Expression) {
        this.left = l;
        this.right = r;
    }

    public Interpret(): number {
        return this.left.Interpret() + this.right.Interpret();
    }
}

// 测试调用
const NUM_A = 10;
const NUM_B = 20;
let a = new Num_Expression(NUM_A);
let b = new Num_Expression(NUM_B);
let add = new Add_Expression(a, b);
console.log("表达式计算结果:", add.Interpret());

行为型模式整体总结

  1. 流程固定、步骤可变 → 模板方法模式
  2. 多分支算法切换 → 策略模式
  3. 一对多消息通知 → 观察者模式
  4. 统一遍历不同集合 → 迭代器模式
  5. 多级请求逐级处理 → 责任链模式
  6. 操作封装、支持撤销队列 → 命令模式
  7. 对象状态快照备份恢复 → 备忘录模式
  8. 多对象解耦统一通信 → 中介者模式
  9. 对象行为随状态变化 → 状态模式
  10. 稳定结构、频繁新增操作 → 访问者模式
  11. 小型自定义语法解析 → 解释器模式

行为型模式核心解决对象间交互、业务流程、算法分支、状态流转问题,配合之前讲解的创建型、结构型模式,完整覆盖 23 种设计模式。全部示例代码严格遵循统一编码规范,可直接在 TypeScript / Node.js 环境运行,在业务开发中按需选用,有效降低代码耦合、提升项目长期可维护性。

更多推荐