讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

updream

一键生成高质量推广成片

AniShort
AniShort

AI短剧协同制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

面向对象设计中的渲染逻辑分离:使用策略模式与多态实现关注点解耦

陌墨同学_5418

陌墨同学_5418

发布时间:2026-02-27 18:44:02

|

476人浏览过

|

来源于php中文网

原创

面向对象设计中的渲染逻辑分离:使用策略模式与多态实现关注点解耦

本文介绍如何通过策略模式与多态重构臃肿的 ui 渲染逻辑,将数据模型(collection/row)与视图呈现(html 生成、交互处理、验证等)彻底分离,提升可维护性与可扩展性。

本文介绍如何通过策略模式与多态重构臃肿的 ui 渲染逻辑,将数据模型(collection/row)与视图呈现(html 生成、交互处理、验证等)彻底分离,提升可维护性与可扩展性。

在现代 Web 应用开发中,当业务数据模型(如 Collection 和 Row)同时承担数据管理、状态维护、DOM 渲染、事件绑定、表单验证乃至文件上传等多重职责时,代码极易膨胀——正如问题中描述的“单个 Row 对象超 1000 行”,不仅难以测试、调试成本高,更严重阻碍功能迭代。根本症结在于违反单一职责原则(SRP)与关注点分离(SoC)。解决方案并非简单拆分文件或新建工具类,而应借助面向对象设计的核心思想进行结构性重构。

✅ 推荐方案:策略模式 + 多态渲染(Polymorphic Rendering)

核心思路是:让每种数据类型(如 SaleRecord、UserProfile、ProductImage)拥有专属的渲染器(Renderer),并通过统一接口实现多态调用。数据模型仅负责持有数据与委托渲染,不再感知 HTML 结构或 DOM 操作细节。

? 实现步骤示意

  1. 定义抽象渲染器接口
    所有渲染器实现统一方法(如 render(row) 和 bindEvents(el, row)),确保可插拔:
// renderer.js
class Renderer {
  render(row) { throw new Error('render() must be implemented'); }
  bindEvents(container, row) { /* 可选:默认空实现 */ }
}
  1. 为不同数据类型创建具体渲染器
    每个子类专注一种业务场景的 UI 逻辑,互不干扰:
// sale-record-renderer.js
class SaleRecordRenderer extends Renderer {
  render(row) {
    return `
      <tr data-id="${row.id}">
        <td><strong>${row.customerName}</strong></td>
        <td>$${(row.amount / 100).toFixed(2)}</td>
        <td><input type="checkbox" ${row.isPaid ? 'checked' : ''}></td>
        <td><button class="btn-edit">Edit</button></td>
      </tr>
    `;
  }

  bindEvents(container, row) {
    container.querySelector('.btn-edit').addEventListener('click', () => {
      openSaleEditor(row);
    });
  }
}

// image-upload-renderer.js
class ImageUploadRenderer extends Renderer {
  render(row) {
    return `
      <div class="image-row">
        <img src="${row.thumbnailUrl}" alt="Preview">
        <input type="file" accept="image/*" data-row-id="${row.id}">
        <span class="status">${row.uploadStatus || 'Ready'}</span>
      </div>
    `;
  }

  bindEvents(container, row) {
    const input = container.querySelector('input[type="file"]');
    input.addEventListener('change', (e) => this.handleFileUpload(e, row));
  }

  handleFileUpload(e, row) { /* 专用上传逻辑 */ }
}
  1. 数据模型轻量化:只持引用,不写 HTML
    Row 不再包含千行渲染代码,而是根据类型动态选择渲染器:
// row.js
class Row {
  constructor(data, rendererRegistry = defaultRendererRegistry) {
    this.data = data;
    this.renderer = rendererRegistry.get(data.type); // 如 'sale-record' → SaleRecordRenderer
  }

  toHtml() {
    return this.renderer.render(this);
  }

  attachTo(container) {
    const el = document.createElement('div');
    el.innerHTML = this.toHtml();
    container.appendChild(el.firstElementChild);
    this.renderer.bindEvents(el.firstElementChild, this);
  }
}
  1. 注册中心统一管理映射关系
    解耦类型与渲染器,便于配置与测试:
// renderer-registry.js
const rendererRegistry = new Map();

rendererRegistry.set('sale-record', new SaleRecordRenderer());
rendererRegistry.set('user-profile', new UserProfileRenderer());
rendererRegistry.set('product-image', new ImageUploadRenderer());

export function getRenderer(type) {
  const renderer = rendererRegistry.get(type);
  if (!renderer) throw new Error(`No renderer registered for type: ${type}`);
  return renderer;
}

⚠️ 关键注意事项

  • 避免“渲染器”变相成为新上帝对象:每个渲染器仍需遵守 SRP —— 仅处理 该类型 的展示与轻量交互;复杂业务逻辑(如校验规则、API 调用)应下沉至独立 Service 层。
  • DOM 操作需谨慎封装:推荐使用 document.createElement 或轻量模板库(如 HyperHTML、htm),避免直接拼接字符串带来的 XSS 风险与可维护性问题。
  • 性能考量:对高频更新的列表(如实时表格),需结合虚拟滚动、事件委托(而非每个 Row 绑定事件)及 requestIdleCallback 优化。
  • 服务端渲染(SSR)友好性:此模式天然支持同构渲染 —— 渲染器可同时运行于 Node.js(生成初始 HTML)与浏览器(补全交互)。

? 总结

与其在原有结构上“打补丁”(如拆分 collection_displayBehaviours.js)或退化为过程式工具函数(如 htmlTableConstructor.js),不如拥抱多态:用类型驱动行为,用组合替代继承,用协议(接口)保障协作。这不仅是代码组织方式的升级,更是构建可演进、易测试、团队协作友好的前端架构的关键一步。重构起点不必宏大——从一个最复杂的 Row 类型开始,为其提取专属渲染器,你将立刻感受到清晰度与可控性的提升。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3511

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

574

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

602

2026.02.12

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

7755

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

382

2025.11.27

C++ 面向对象编程与设计模式实践
C++ 面向对象编程与设计模式实践

本专题整合了 C++ 面向对象编程的核心机制,涵盖类的定义与访问控制、构造函数与析构函数、拷贝语义与移动语义、继承与虚函数多态、抽象类与接口、运算符重载、友元函数等关键知识点,同时结合单例模式、工厂模式、观察者模式、策略模式等常用设计模式的 C++ 实现,帮助开发者写出结构清晰、易于维护的面向对象代码。

384

2026.04.09

Java 面向对象与核心编程机制
Java 面向对象与核心编程机制

系统讲解 Java 面向对象编程的核心知识体系,涵盖类的定义与封装、构造方法与 this/super 关键字、继承与方法重写、多态与向上向下转型、抽象类与接口的区别与设计原则、异常处理机制(try-catch-finally / 自定义异常)、泛型的类型参数与通配符、集合框架(List/Set/Map)的使用与遍历方式,帮助开发者全面掌握 Java 程序设计的核心机制与面向对象思维。

263

2026.04.17

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

375

2025.11.27

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn