<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[深入浅出制作全自动Mud机器人-组件化]]></title><description><![CDATA[<p dir="auto">在全自动Mud机器人开发，以及长期的运维更新时，我觉得引入组件化是一件非常重要的底层架构。</p>
<p dir="auto">组件化，看起来是一个和模块化接近的概念。但本质完全不同。</p>
<p dir="auto">在我眼里，模块化是将相关的代码进行组织和封装，对外提供统一接口的一种代码组织形式。</p>
<p dir="auto">组件化的确要依赖于模块化是实现功能。但更重要的是，组件化的目标是</p>
<p dir="auto"><strong>可替代可废弃性。</strong></p>
<p dir="auto">随着Mud的更新，代码不应该进行大幅度的调整，还是废弃部分组件，新建部分组件，调整部分组件。这样，机器可以先将重点组件进行调整，然后临时禁用不重要的组件，甚至部分影响不大的组件带病工作，实现机器的边开发边运行。</p>
<p dir="auto">既将代码根据易变程度分为不同的组织，确保核心代码的稳定性，然后组件中可以用各种快速/不健全/临时性的机制确保特殊状态下机器的可用性，以及确保机器处于一种可以从小到大，逐渐成长的状态。</p>
<p dir="auto">为了实现这个目的，组件化需要实现的功能是</p>
<h2>组件标准化</h2>
<p dir="auto">同一类的组件，应该有相同的接口和核心代码进行交互。这样，核心代码才能在调整主键时不需要关注细节和深入。</p>
<p dir="auto">以我的newhelljs为例，使用了多种组件</p>
<ul>
<li>角色准备阶段的<a href="https://github.com/hellclient-scripts/newhelljs/blob/main/script/src/core/prepare.js" target="_blank" rel="noopener noreferrer nofollow ugc">提案组件</a><br />
通过通用的Submit参数，实现判断是否进入某个准备阶段</li>
<li>任务本身的[Quest组件](<a href="https://github.com/hellclient-scripts/newhelljs/blob/main/script/src/core/quests.js" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/hellclient-scripts/newhelljs/blob/main/script/src/core/quests.js</a><br />
通过Ready参数，Cooldown属性，OnHUD/OnSummary|OnReport等接口，实现了人物与核心代码的隔离</li>
<li>配置的<a href="https://github.com/hellclient-scripts/newhelljs/blob/main/script/src/core/quests.js" target="_blank" rel="noopener noreferrer nofollow ugc">Condition组件</a><br />
使得是否接任务/是否使用某个技能等等，都与核心代码无关，完全通过定义新的Condition实现。</li>
</ul>
<p dir="auto">很明显，组件标准化和能区分组件代码和核心代码的前提。如果不对组件进行标准化，则可扩展性可维护性也成了无根之水。</p>
<h2>控制反转</h2>
<p dir="auto">控制反转(IOC)是一个常见的程序开发思路。</p>
<p dir="auto">所谓的反转，就是将** 主程序创建类后，初始化类** 反转为  ** 主程序只负责创建类，类自行初始化)</p>
<p dir="auto">实现了控制反转后，才能实现组件的封装，将组件与核心代码分离。</p>
<p dir="auto">核心代码只负责两件事情:</p>
<p dir="auto">如果你随手搜索一下,可能会发现一大堆依赖注入，工厂模式什么的复杂东西。</p>
<p dir="auto">不用管那些，那些主要是对强OOP，静态编译的Java强调的东西。</p>
<p dir="auto">对于js/lua的实现，参考我上面的例子中，都会传入一个函数作为参数就可以了。</p>
<p dir="auto">把初始化函数放在组件的制定位置，核心代码创建组件后，把配置作为参数带入初始化函数就可以了。</p>
<p dir="auto">这里说的控制反转，只是提醒一下，不要在核心端去设置组件，让组件自包含。</p>
<h2>全局注册</h2>
<p dir="auto">全局注册很简单，就是建立一个全局的object/table变量,给每一个组件起一个唯一的字符串主键，将组件或者组件的生成函数都放在里面就行。</p>
<p dir="auto">全局注册的目的是</p>
<ul>
<li>在进行组件的替换/更新甚至顺序调整时，无需调整核心代码，只需要调整某个配置即可。</li>
<li>通过同一的调用方式，确保不会有其他位置的代码来直接调用组件内的代码，避免组件修改时出现全局问题。</li>
<li>方便的管理方式，能很容易的明白有多少个可用模块，不用去各个代码目录里寻找。</li>
</ul>
<p dir="auto">使用全局注册要注意的点是</p>
<ul>
<li>只通过 注册的表 与组件交互，不建立直接处理的代码</li>
<li>在多个组件交互时，可以通过给组件加接口/全局事件/核心组里注册特殊毁掉的方式来处理。</li>
</ul>
<h2>重要的点</h2>
<p dir="auto">使用组件模式，其实是按照我们最初的目的来使用，也就是</p>
<ul>
<li>将代码分为干净的核心代码，和脏(与业务更接近)的组件代码。确保代码指令控制在一个基本的可用度上。</li>
<li>通过配置，设置，能动态的调整激活的模块，实现更复杂的功能。</li>
</ul>
<p dir="auto">技术只是手段，代码如何处理，不一定要强求某个模式，还是为了实际目的服务。</p>
]]></description><link>https://forum.hellclient.com/topic/10/深入浅出制作全自动mud机器人-组件化</link><generator>RSS for Node</generator><lastBuildDate>Fri, 13 Mar 2026 20:32:55 GMT</lastBuildDate><atom:link href="https://forum.hellclient.com/topic/10.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 08 Jan 2026 09:35:59 GMT</pubDate><ttl>60</ttl></channel></rss>