0

0

面向对象渲染:用多态替代条件分支实现展示逻辑解耦

花韻仙語

花韻仙語

发布时间:2026-02-27 19:11:01

|

156人浏览过

|

来源于php中文网

原创

面向对象渲染:用多态替代条件分支实现展示逻辑解耦

本文介绍如何通过多态设计模式将数据对象的渲染职责(html生成、ui控件绘制)与业务逻辑(数据验证、状态管理、交互处理)彻底分离,避免单个类膨胀至千行代码,提升可维护性与可扩展性。

本文介绍如何通过多态设计模式将数据对象的渲染职责(html生成、ui控件绘制)与业务逻辑(数据验证、状态管理、交互处理)彻底分离,避免单个类膨胀至千行代码,提升可维护性与可扩展性。

在 Web 应用中,当“数据模型”(如 Row 或 Collection)同时承担数据管理、状态变更、用户交互和 UI 渲染多重职责时,极易陷入“上帝对象”困境——例如一个 Row 类因需支持 10+ 种字段类型(文本、复选框、图片上传、日期选择器等)而突破 1000 行,导致修改风险高、测试困难、复用性差。

根本解法不是简单地按文件拆分(如 row.js + row_display.js),也不是另建一个通用构造器(如 HtmlTableConstructor)来集中处理所有渲染逻辑——后者会演变为新的巨型过程式模块,违背单一职责原则。真正可持续的架构升级,是将“如何渲染自己”这一能力,下放给每个具体数据类型的专属渲染器,通过多态实现动态委派。

✅ 推荐方案:策略模式 + 多态渲染器(Renderer Pattern)

核心思想:让每种数据类型拥有自己的渲染器(Renderer),模型对象只负责持有数据与行为,渲染动作委托给对应的 Renderer 实例。

行者AI
行者AI

行者AI绘图创作,唤醒新的灵感,创造更多可能

下载

示例结构(ES6 Class + Composition)

// models/Row.js
class Row {
  constructor(data, schema) {
    this.data = data;
    this.schema = schema; // e.g., { field: 'status', type: 'radio', options: [...] }
  }

  // 渲染委托:不写 HTML,只决定用哪个 renderer
  getRenderer() {
    const type = this.schema.type;
    switch (type) {
      case 'text':     return new TextRenderer(this);
      case 'checkbox': return new CheckboxRenderer(this);
      case 'image':    return new ImageRenderer(this);
      case 'sale-record': return new SaleRecordRenderer(this); // 业务专属
      default:         throw new Error(`No renderer for type: ${type}`);
    }
  }
}

// renderers/TextRenderer.js
class TextRenderer {
  constructor(row) {
    this.row = row;
  }
  render() {
    return `<td><input type="text" value="${escapeHtml(this.row.data.value)}"></td>`;
  }
}

// renderers/SaleRecordRenderer.js —— 可独立开发、测试、复用
class SaleRecordRenderer {
  constructor(row) {
    this.row = row;
  }
  render() {
    const { amount, currency, date } = this.row.data;
    return `
      <td class="sale-cell">
        <strong>${amount} ${currency}</strong>
        <div class="date">${new Date(date).toLocaleDateString()}</div>
        <button onclick="editSale(${this.row.data.id})">编辑</button>
      </td>
    `;
  }
  // 也可封装交互逻辑(与视图强相关部分)
  bindEvents() {
    document.querySelector(`[data-sale-id="${this.row.data.id}"] .edit-btn`)
      .addEventListener('click', () => this.handleEdit());
  }
  handleEdit() { /* 业务专属编辑流程 */ }
}

在 Collection 中统一协调

// models/Collection.js
class Collection {
  constructor(rows, schema) {
    this.rows = rows;
    this.schema = schema;
  }

  renderTable() {
    const headers = this.schema.map(f => `<th>${f.label}</th>`).join('');
    const bodyRows = this.rows.map(row => {
      const renderer = row.getRenderer();
      return renderer.render(); // 多态调用,无需 if/else
    }).join('');

    return `
      <table class="data-table">
        <thead><tr>${headers}</tr></thead>
        <tbody>${bodyRows}</tbody>
      </table>
    `;
  }

  // 批量挂载交互事件(可选)
  mountInteractions() {
    this.rows.forEach(row => {
      const renderer = row.getRenderer();
      if (typeof renderer.bindEvents === 'function') {
        renderer.bindEvents();
      }
    });
  }
}

? 关键优势与实践建议

  • 开闭原则落地:新增字段类型(如 signature-canvas)只需新增 SignatureRenderer 类,无需修改 Row 或 Collection;
  • 关注点分离清晰
    • Row:专注数据结构、校验规则、CRUD 接口;
    • Renderer:专注视觉呈现、DOM 操作、轻量级事件绑定;
  • 可测试性强:每个 Renderer.render() 方法可独立单元测试,输入数据 → 输出 HTML 字符串,无副作用;
  • 支持渐进重构:可先从高频字段(如 image, date)开始抽取 Renderer,再逐步迁移其余逻辑;
  • 注意 XSS 防护:示例中 escapeHtml() 必须实现(推荐使用 DOMPurify.sanitize() 或原生 textContent 替代内联插值);
  • 避免过度设计:若仅有 2–3 种简单字段,可先用工厂函数 + 纯函数渲染器(renderText(row)),再演进为类。

? 进阶提示:结合现代框架(React/Vue)时,该模式自然映射为「组件化」——SaleRecordRenderer 即 SaleRecordCell.vue;而在纯 DOM 场景中,它正是你缺失的、面向对象的 UI 分层基石。

通过将“绘制自己”的能力从模型中剥离并交由多态 Renderer 承担,你不仅解决了代码臃肿问题,更构建了一套可生长、易协作、抗变化的前端架构范式。

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

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

196

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

231

2025.12.24

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

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

312

2023.10.31

php数据类型
php数据类型

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

223

2025.10.31

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

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

97

2026.02.12

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

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

57

2025.09.05

java面向对象
java面向对象

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

61

2025.11.27

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

2

2026.02.27

热门下载

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

精品课程

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号