<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> 领域驱动设计 </title> <meta name="description" content=""> <meta name="keywords" content=""> <meta name="author" content="Mozzie"> <link rel="canonical" href="https://mozzie.cn/2023/11/06/front-end/ddd/"> <link rel="icon" type="image/svg" href='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 7h1a2 2 0 0 1 2 2v.5a.5.5 0 0 0 .5.5a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5a.5.5 0 0 0-.5.5v.5a2 2 0 0 1-2 2h-2"></path><path d="M8 7H6a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h1"></path><path d="M12 8l-2 4h3l-2 4"></path></g></svg>'> <link rel="stylesheet" href="/css/4d4ea9c6.css"> <meta name="generator" content="Hexo 6.3.0"></head> <body id="app"> <!-- 响应式布局按钮 --> <a class="side-navigation btn-hover btn-hover-bg tip left" data-tip="Expand"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="4" y="4" width="16" height="16" rx="2"></rect> <path d="M9 4v16"></path> </g> </svg> </a> <aside> <div> <link rel="stylesheet" href="/css/5bfc518f.css"> <div class="home-bar"> <a href="/" class="tip" data-tip="Home"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"> <path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22c18.2 6.8 31.3 24.4 31.3 45c0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7c54.4-11.4 98.3-55.4 109.7-109.7c17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9c129.4 7 233.4 112 240.9 241.5c.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9c76.8 6.3 138 68.2 144.9 145.2c.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3c-8.4-110.1-96.5-198.2-206.6-206.7z" fill="currentColor"></path> </svg> <span>Mozzie</span> </a> <!-- 切换主题 --> <a id="toggle-theme" class="tip left" data-tip="Switch Theme"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"> <path d="M256 118a22 22 0 0 1-22-22V48a22 22 0 0 1 44 0v48a22 22 0 0 1-22 22z" fill="currentColor"></path> <path d="M256 486a22 22 0 0 1-22-22v-48a22 22 0 0 1 44 0v48a22 22 0 0 1-22 22z" fill="currentColor"></path> <path d="M369.14 164.86a22 22 0 0 1-15.56-37.55l33.94-33.94a22 22 0 0 1 31.11 31.11l-33.94 33.94a21.93 21.93 0 0 1-15.55 6.44z" fill="currentColor"></path> <path d="M108.92 425.08a22 22 0 0 1-15.55-37.56l33.94-33.94a22 22 0 1 1 31.11 31.11l-33.94 33.94a21.94 21.94 0 0 1-15.56 6.45z" fill="currentColor"></path> <path d="M464 278h-48a22 22 0 0 1 0-44h48a22 22 0 0 1 0 44z" fill="currentColor"></path> <path d="M96 278H48a22 22 0 0 1 0-44h48a22 22 0 0 1 0 44z" fill="currentColor"></path> <path d="M403.08 425.08a21.94 21.94 0 0 1-15.56-6.45l-33.94-33.94a22 22 0 0 1 31.11-31.11l33.94 33.94a22 22 0 0 1-15.55 37.56z" fill="currentColor"></path> <path d="M142.86 164.86a21.89 21.89 0 0 1-15.55-6.44l-33.94-33.94a22 22 0 0 1 31.11-31.11l33.94 33.94a22 22 0 0 1-15.56 37.55z" fill="currentColor"></path> <path d="M256 358a102 102 0 1 1 102-102a102.12 102.12 0 0 1-102 102z" fill="currentColor"></path> </svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"> <path d="M264 480A232 232 0 0 1 32 248c0-94 54-178.28 137.61-214.67a16 16 0 0 1 21.06 21.06C181.07 76.43 176 104.66 176 136c0 110.28 89.72 200 200 200c31.34 0 59.57-5.07 81.61-14.67a16 16 0 0 1 21.06 21.06C442.28 426 358 480 264 480z" fill="currentColor"></path> </svg> </a> </div> <script src="/js/ae2a0e7b.js"></script> <!-- search --> <link rel="stylesheet" href="/css/3320a187.css"> <form class="search-group"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20"> <g fill="currentColor"> <path d="M8.5 3a5.5 5.5 0 0 1 4.383 8.823l4.147 4.147a.75.75 0 0 1-.976 1.133l-.084-.073l-4.147-4.147A5.5 5.5 0 1 1 8.5 3zm0 1.5a4 4 0 1 0 0 8a4 4 0 0 0 0-8z" fill="currentColor"></path> </g> </svg> <span id="search-input">Search...</span> <div class="short-key"> <kbd class="key-cap"><span>Ctrl K</span></kbd> </div> </form> <script> window.algolia = { appId: "5DTW808BZ8", SearchOnlyAPIKey: "27845b245efc8a2853cc0bdc7366ea26" } window.search = { enable: "true" } </script> <script src="/js/9f145c31.js"></script> <!-- navigation --> <link rel="stylesheet" href="/css/3efc6cb5.css"> <section class="category-nav scrollbar-obtrusive"> <ul class="nav-items"> <li data-path="archives"> <a href="/archives"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 7v14"></path> <path d="M9 18l3 3l3-3"></path> <circle cx="12" cy="5" r="2"></circle> </g> </svg> <div class="ellipsis">Timeline</div> </a> </li> <li data-path="roadmap"> <a href="/roadmap"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M10.5 20.4l-6.9-6.9c-.781-.781-.781-2.219 0-3l6.9-6.9c.781-.781 2.219-.781 3 0l6.9 6.9c.781.781.781 2.219 0 3l-6.9 6.9c-.781.781-2.219.781-3 0z"></path> <path d="M9 14v-2c0-.59.414-1 1-1h5"></path> <path d="M13 9l2 2l-2 2"></path> </g> </svg> <div class="ellipsis">Roadmap</div> </a> </li> <li data-path="resume"> <a href="/resume"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 3v4a1 1 0 0 0 1 1h4"></path> <path d="M5 8V5a2 2 0 0 1 2-2h7l5 5v11a2 2 0 0 1-2 2h-5"></path> <circle cx="6" cy="14" r="3"></circle> <path d="M4.5 17L3 22l3-1.5L9 22l-1.5-5"></path> </g> </svg> <div class="ellipsis">Resume</div> </a> </li> </ul> <p>Category</p> <ul> <li class=""> <a href="/categories/EQ/"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5.636 5.636a9 9 0 0 1 13.397.747L13.414 12l5.619 5.617A9 9 0 1 1 5.636 5.636z"></path><circle cx="11.5" cy="7.5" r="1" fill="currentColor"></circle></g></svg> <div class="ellipsis"> <span> EQ </span> </div> </a> </li> <li class=""> <a href="/categories/Hexo/"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1"></path><path d="M8 16h8"></path><path d="M8.322 12.582l7.956.836"></path><path d="M8.787 9.168l7.826 1.664"></path><path d="M10.096 5.764l7.608 2.472"></path></g></svg> <div class="ellipsis"> <span> Hexo </span> </div> </a> </li> <li class=""> <a href="/categories/Finance/"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"></circle><path d="M14.8 9A2 2 0 0 0 13 8h-2a2 2 0 0 0 0 4h2a2 2 0 0 1 0 4h-2a2 2 0 0 1-1.8-1"></path><path d="M12 6v2m0 8v2"></path></g></svg> <div class="ellipsis"> <span> Finance </span> </div> </a> </li> <li class="active"> <a href="/categories/Front-End/"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 4l-2 14.5l-6 2l-6-2L4 4z"></path><path d="M7.5 8h3v8l-2-1"></path><path d="M16.5 8H14a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h1.423a.5.5 0 0 1 .495.57L15.5 15.5l-2 .5"></path></g></svg> <div class="ellipsis"> <span> Front-End </span> </div> </a> </li> </ul> </section> <script src="/js/f8b20eb9.js"></script> <!-- icp --> <div class="icp"> <a target="_blank" rel="noopener" href="http://beian.miit.gov.cn/">苏ICP备19008833号-4</a> </div> </div> </aside> <main> <link rel="stylesheet" href="/css/3d0c4c23.css"> <div class="post-container"> <div class="content"> <header> <link rel="stylesheet" href="/css/de5de8fb.css"> <nav class="breadcrumb"> <a href="/" class="home tip btn-hover right" data-tip="Home"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512"> <path d="M172.2 226.8c-14.6-2.9-28.2 8.9-28.2 23.8V301c0 10.2 7.1 18.4 16.7 22c18.2 6.8 31.3 24.4 31.3 45c0 26.5-21.5 48-48 48s-48-21.5-48-48V120c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v248c0 89.5 82.1 160.2 175 140.7c54.4-11.4 98.3-55.4 109.7-109.7c17.4-82.9-37-157.2-112.5-172.2zM209 0c-9.2-.5-17 6.8-17 16v31.6c0 8.5 6.6 15.5 15 15.9c129.4 7 233.4 112 240.9 241.5c.5 8.4 7.5 15 15.9 15h32.1c9.2 0 16.5-7.8 16-17C503.4 139.8 372.2 8.6 209 0zm.3 96c-9.3-.7-17.3 6.7-17.3 16.1v32.1c0 8.4 6.5 15.3 14.8 15.9c76.8 6.3 138 68.2 144.9 145.2c.8 8.3 7.6 14.7 15.9 14.7h32.2c9.3 0 16.8-8 16.1-17.3c-8.4-110.1-96.5-198.2-206.6-206.7z" fill="currentColor"></path> </svg> </a> <em> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20"> <g fill="none"> <path d="M7.733 4.207a.75.75 0 0 1 1.06.026l5.001 5.25a.75.75 0 0 1 0 1.035l-5 5.25a.75.75 0 1 1-1.087-1.034L12.216 10l-4.51-4.734a.75.75 0 0 1 .027-1.06z" fill="currentColor"></path> </g> </svg> </em> <a href="/categories/Front-End/"> Front-End </a> <em> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20"> <g fill="none"> <path d="M7.733 4.207a.75.75 0 0 1 1.06.026l5.001 5.25a.75.75 0 0 1 0 1.035l-5 5.25a.75.75 0 1 1-1.087-1.034L12.216 10l-4.51-4.734a.75.75 0 0 1 .027-1.06z" fill="currentColor"></path> </g> </svg> </em> <span class="ellipsis"> 领域驱动设计 </span> </nav> <script src="/js/31d6cfe0.js"></script> </header> <main class="scrollbar-obtrusive"> <div class="article-container"> <!-- 文章tags --> <!-- 渲染文章内容 --> <article><h1 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h1><ul> <li><a target="_blank" rel="noopener" href="https://juejin.cn/post/6844903618680881165">蚂蚁金服数据体验技术团队 - 领域驱动设计</a></li> <li><a target="_blank" rel="noopener" href="https://tech.meituan.com/2017/12/22/ddd-in-practice.html">美团 - 领域驱动设计在互联网业务开发中的实践</a></li> <li><a target="_blank" rel="noopener" href="https://huhao.dev/posts/61190ae2/#%E9%97%AE%E9%A2%98%E5%AD%90%E5%9F%9F%E8%AF%86%E5%88%AB">领域驱动实战思考</a></li> <li><a target="_blank" rel="noopener" href="https://www.tangshuang.net/8663.html">基于 DDD 的前端项目架构设计与实战</a></li> <li><a target="_blank" rel="noopener" href="https://www.tangshuang.net/8212.html">React 语境下前端 DDD 的思考</a></li> </ul> <h1 id="架构对比"><a href="#架构对比" class="headerlink" title="架构对比"></a>架构对比</h1><p>从后端视角看,对比传统的三层架构,领域驱动</p> <ul> <li><code>充血</code>复用了:领域对外的接口</li> <li><code>领域服务</code>封装了:领域之间的联系</li> </ul> <p>贫血模型->充血模型,降低了<code>service层</code>的负担,同时保证了业务迭代,<code>entity</code>的独立性</p> <h2 id="MVC"><a href="#MVC" class="headerlink" title="MVC"></a>MVC</h2><p>从数据库视角、分析实体出发,进行系统的构建</p> <ul> <li>DAO 层</li> <li>Service 层</li> <li>Controller 层</li> </ul> <h2 id="后端-DDD"><a href="#后端-DDD" class="headerlink" title="后端 DDD"></a>后端 DDD</h2><blockquote> <p>针对基础设施层,也可以考虑加入<code>防腐层</code>、<code>工厂</code></p> </blockquote> <p>一个领域基本四层架构</p> <ol> <li>用户层(user interface): 对标 controller,对外提供 web 服务、接口</li> <li>应用层(application): 业务层,定义领域可以解决的问题 <code>domainService</code></li> <li>领域层(domain): 纯粹的描述业务实体</li> <li>基础设施层(infra): 持久化层(Builder+repository)</li> </ol> <p>同时,领域拆分带来如下两个致命问题</p> <ul> <li>领域化(微服务)后,数据库是分开的,导致实体调用链复杂,避免跨库查询</li> <li>避免分布式事务同步</li> </ul> <h2 id="前端-DDD"><a href="#前端-DDD" class="headerlink" title="前端 DDD"></a>前端 DDD</h2><blockquote> <p>?? 这里存在一个问题,api 网关到底要不要挪到前端领域目录下来开发</p> </blockquote> <ol> <li>用户层: web、mobile、mini-program …多端</li> <li>service: 暴露给 UI 组件的 <code>domainSerivce</code>,组织实体的状态流转</li> <li>entity: 实体、聚合实体、事件</li> <li>infra: api 请求、缓存、工具</li> </ol> <h2 id="工厂-Factory-x2F-Builder"><a href="#工厂-Factory-x2F-Builder" class="headerlink" title="工厂 Factory / Builder"></a>工厂 Factory / Builder</h2><ul> <li>数据库表设计层面,如果要<code>多对多</code>的关系,只能很别扭的设计一个中间表。</li> <li>实体 A 适合 <code>mongo</code>文档形存储,实体 B 适合<code>mysql</code>关系型存储。对于 <code>Builder</code> 而言,直接在这个领域搓出来 <code>A 和 B</code> 的 <code>CRUD</code>的实现方法</li> </ul> <h2 id="防腐层-Facade-x2F-Adaptor"><a href="#防腐层-Facade-x2F-Adaptor" class="headerlink" title="防腐层 Facade / Adaptor"></a>防腐层 Facade / Adaptor</h2><p>也被成为适配器,隔离第三方/外部服务,例如场景,用户上传文件到阿里云、腾讯云</p> <pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">UserUploadServiceFacade</span> <span class="token keyword">extends</span> <span class="token class-name">UserService</span> <span class="token punctuation">{</span> <span class="token comment">/** * 上传 */</span> <span class="token keyword">async</span> <span class="token function">upload</span><span class="token punctuation">(</span><span class="token parameter">oss</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>oss <span class="token operator">===</span> <span class="token string">"ali"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">"OK"</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>oss <span class="token operator">===</span> <span class="token string">"tx"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token string">"FAIL"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre> <h1 id="领域模型"><a href="#领域模型" class="headerlink" title="领域模型"></a>领域模型</h1><p>实体的<code>贫血->充血</code>是一个随着业务发展过程演变的结果,初期业务场景不明确,很难充血,瞎几把充血,纯属找难受。</p> <p>是否需要引入<code>聚合根(aggregate root)</code>的概念,解决领域内实体独立、平铺关系带来的不方便,这个可能比较看心情</p> <h2 id="贫血模型-POJO-的问题"><a href="#贫血模型-POJO-的问题" class="headerlink" title="贫血模型(POJO)的问题"></a>贫血模型(POJO)的问题</h2><blockquote> <p>脱离了业务复杂度谈分层,好比抛开剂量谈毒性</p> </blockquote> <p>领域对象里只有<code>get/set</code>方法,所有的业务逻辑都不包含在内,从而造成<code>失忆症</code>,从实体中,无法知道发生了那些业务,需要去 <code>service层</code> 里挨个梳理,一旦业务迭代、<code>service 层</code>直接开始变成屎山</p> <h2 id="充血模型-amp-amp-领域服务的关系"><a href="#充血模型-amp-amp-领域服务的关系" class="headerlink" title="充血模型 && 领域服务的关系"></a>充血模型 && 领域服务的关系</h2><blockquote> <p>确保领域之间独立的,随着不断的充血,保证领域(实体)是独立发展的</p> </blockquote> <p>假定两个 domain(实体):</p> <ul> <li>学生: 上课、做作业</li> <li>老师、全体起立、布置作业</li> </ul> <p>假定<code>老师</code>调用<code>全体起立</code>,对应肯定要<code>学生</code>调用<code>上课</code>,这个就是 <code>领域服务(domainService)</code> 需要去处理的,他俩不能建立直接的联系。</p> <ul> <li>增加新的业务逻辑:在 <code>domainService</code> 增加新的方法。</li> <li>调整旧的业务逻辑:修改<code>学生</code>,<code>老师</code>,内部具体的方法,<code>domainService</code> 完全不需要变化。</li> </ul> </article> <link rel="stylesheet" href="/css/80d65618.css"> <div class="copyright"> <a target="_blank" href="https://mozzie.cn/2023/11/06/front-end/ddd/"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M3 19a9 9 0 0 1 9 0a9 9 0 0 1 9 0"></path> <path d="M3 6a9 9 0 0 1 9 0a9 9 0 0 1 9 0"></path> <path d="M3 6v13"></path> <path d="M12 6v13"></path> <path d="M21 6v13"></path> </g> </svg> <span>领域驱动设计</span> </a> <ul> <li> <span>Author</span> <p> Mozzie</p> </li> <li> <span>Published on</span> <p>2023-11-06</p> </li> <li> <span>License</span> <p><a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a></p> </li> </ul> </div> <script src="/js/31d6cfe0.js"></script> <!-- 评论 --> <div id="vcomments"></div> </div> </main> </div> <div class="meta-container"> <div class="toc-wrapper content-dialog"> <p class="catalog"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"> <g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M4 6h16"></path> <path d="M4 12h16"></path> <path d="M4 18h12"></path> </g> </svg> <span>Catalog</span> </p> <!-- 文章toc --> <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE"><span class="toc-number">1.</span> <span class="toc-text">参考文献</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%9E%B6%E6%9E%84%E5%AF%B9%E6%AF%94"><span class="toc-number">2.</span> <span class="toc-text">架构对比</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#MVC"><span class="toc-number">2.1.</span> <span class="toc-text">MVC</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%90%8E%E7%AB%AF-DDD"><span class="toc-number">2.2.</span> <span class="toc-text">后端 DDD</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E7%AB%AF-DDD"><span class="toc-number">2.3.</span> <span class="toc-text">前端 DDD</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B7%A5%E5%8E%82-Factory-x2F-Builder"><span class="toc-number">2.4.</span> <span class="toc-text">工厂 Factory / Builder</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%98%B2%E8%85%90%E5%B1%82-Facade-x2F-Adaptor"><span class="toc-number">2.5.</span> <span class="toc-text">防腐层 Facade / Adaptor</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E9%A2%86%E5%9F%9F%E6%A8%A1%E5%9E%8B"><span class="toc-number">3.</span> <span class="toc-text">领域模型</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B4%AB%E8%A1%80%E6%A8%A1%E5%9E%8B-POJO-%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-number">3.1.</span> <span class="toc-text">贫血模型(POJO)的问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%85%E8%A1%80%E6%A8%A1%E5%9E%8B-amp-amp-%E9%A2%86%E5%9F%9F%E6%9C%8D%E5%8A%A1%E7%9A%84%E5%85%B3%E7%B3%BB"><span class="toc-number">3.2.</span> <span class="toc-text">充血模型 && 领域服务的关系</span></a></li></ol></li></ol> </div> </div> </div> <script> window.katex = { enable: "true", jsCdn: "//cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.js", cssCdn: "//cdn.jsdelivr.net/npm/katex@0.13.18/dist/katex.min.css" } window.mermaid = { enable: "true", cdn: "//cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js", } window.valine = { enable: "false", appId: 'TisMit6uhflounFqAN3ZGjgq-MdYXbMMI', appKey: 'CdjirjYdz07U5i62ElsJvXUh', avatar: 'monsterid', cdn: '//unpkg.com/valine@latest/dist/Valine.min.js', serverURLs: '//tismit6u.api.lncldglobal.com' }; </script> <script src="/js/a02fa72b.js"></script> </main> </body> <script> window.i18n = { "tip-collapse": "Collapse", "tip-expand": "Expand", "text-select": "select", "text-move": "movement", "text-esc": "close", "tip-status-done": "Done", "tip-status-doing": "In Progress", "tip-status-todo": "Todo", "tip-status-other": "Duplicate", "tip-status-default": "Default", "tip-roadmap-today": "Positioning to the today", "text-search": "Search...", "text-today": "Today", // month "January": "January", "February": "February", "March": "March", "April": "April", "May": "May", "June": "June", "July": "July", "August": "August", "September": "September", "October": "October", "November": "November", "December": "December", } </script> <script src="/js/58c91c4e.js"></script> </html>