第61章 Renderer
1. Renderer 定义
Renderer 是 SATE 中负责将已经确定的结构化表现数据转换为具体表现形式的组件。
前面的 Expression 定义了“需要表现什么”,Template 定义了“按照什么结构表现”,而 Renderer 负责确定:
这些结构化内容最终应该以什么表现形式输出。
基本关系:
Expression
↓
Template
↓
Renderer
↓
Rendered Result
Renderer 本身不负责:
- 感知
- 认知
- 理解
- 推理
- 决策
- 学习
- 记忆
Renderer 只处理表现转换。
例如:
Expression
{
type: "RESULT",
data: {
name: "Product A",
state: "available"
}
}
经过不同 Renderer,可以形成:
WebRenderer
→ HTML
UiRenderer
→ UI结构
ApiRenderer
→ JSON/XML
DeviceRenderer
→ 设备可识别的数据或控制表示
因此:
Renderer ≠ Expression
Renderer ≠ Template
Renderer ≠ Adapter
可以定义为:
Renderer 是 SATE 中将 Expression 与 Template 所形成的结构化表现内容转换为指定表现格式的处理组件。
2. Expression → Renderer
Expression 表示内部结果需要如何对外表现,Renderer 则负责完成具体的表现转换。
基本流程:
ICAI Result
↓
Expression
↓
Template
↓
Renderer
↓
Rendered Result
↓
Adapter
↓
External Output
例如:
ActionResult
{
state: "SUCCESS",
output: {
order_id: 1001,
status: "created"
}
}
首先形成 Expression:
Expression
{
type: "RESULT",
target: "user",
data: {
order_id: 1001,
status: "created"
}
}
然后选择 Renderer。
WebRenderer
HTML
<div>
<span>Order: 1001</span>
<span>Status: created</span>
</div>
ApiRenderer
{
"order_id": 1001,
"status": "created"
}
DeviceRenderer
DEVICE_RESULT
ORDER=1001
STATUS=CREATED
因此 Renderer 的核心不是“产生内容”,而是:
Structured Expression
↓
Representation
3. WebRenderer
WebRenderer 用于将 Expression 和 Template 转换为 Web 环境可以使用的表现结果。
最典型的结果是 HTML。
例如:
Expression
{
type: "RESULT",
data: {
title: "Product",
name: "Electric Toothbrush",
state: "available"
}
}
Template:
<h1>{{title}}</h1>
<div class="product">
<h2>{{name}}</h2>
{{if state == "available"}}
<span>Available</span>
{{else}}
<span>Unavailable</span>
{{/if}}
</div>
经过:
Template
↓
TemplateEngine
↓
WebRenderer
↓
HTML
得到:
<h1>Product</h1>
<div class="product">
<h2>Electric Toothbrush</h2>
<span>Available</span>
</div>
WebRenderer 可以负责:
- HTML 文本
- HTML 属性
- 页面结构
- 表格
- 列表
- 状态显示
- 页面组件
但它不应该负责:
HTML → 修改认知状态
HTML → 执行推理
HTML → 修改 Memory
这些属于其他系统。
4. UiRenderer
UiRenderer 用于将结构化 Expression 转换为 UI 所需要的结构。
WebRenderer 主要面向 Web 页面表现,而 UiRenderer 更强调:
界面对象、组件、属性和状态的表现结构。
例如:
Expression
{
type: "UI",
component: "ProductCard",
data: {
name: "Product A",
price: 29.90,
state: "available"
}
}
UiRenderer 可以转换为:
UI
{
component: "ProductCard",
properties: {
title: "Product A",
price: 29.90,
state: "available"
}
}
进一步可以形成:
Screen
├── Header
├── ProductCard
│ ├── Name
│ ├── Price
│ └── State
└── Footer
UiRenderer 可以处理:
- UI Component
- Component Property
- Component State
- Layout
- Event 表现定义
- UI 数据绑定结构
例如:
ProductCard
{
title: "Electric Toothbrush",
price: 29.90,
state: "available"
}
需要特别区分:
UiRenderer
↓
表现 UI 状态
Behavior
↓
实际行为
Action
↓
实际行动
例如:
Button.state = "disabled"
只是 UI 表现。
它并不意味着:
Action = disabled
5. ApiRenderer
ApiRenderer 用于将 Expression 转换为 API 可以传输的结构化数据。
常见表现形式包括:
JSON
XML
Structured Text
例如:
Expression
{
type: "RESULT",
data: {
id: 1001,
name: "Product A",
state: "available"
}
}
ApiRenderer 可以输出:
{
"id": 1001,
"name": "Product A",
"state": "available"
}
也可以输出 XML:
<product>
<id>1001</id>
<name>Product A</name>
<state>available</state>
</product>
ApiRenderer 的重点是:
结构稳定
字段明确
类型明确
格式确定
例如:
API Result
{
success: true,
data: {
id: 1001,
state: "available"
},
error: null
}
ApiRenderer 不负责决定:
应该返回什么知识?
应该采取什么行动?
应该选择哪个方案?
这些结果应该已经由前面的认知、推理、决策和 Expression 层确定。
ApiRenderer 只是:
Existing Structured Data
↓
API Representation
6. DeviceRenderer
DeviceRenderer 用于将 Expression 转换为特定设备、终端或系统接口能够识别的表现结构。
例如一个设备状态:
Expression
{
type: "STATE",
target: "Device_A",
data: {
power: "ON",
temperature: 25,
mode: "NORMAL"
}
}
DeviceRenderer 可以转换为:
DEVICE_STATE
POWER=ON
TEMPERATURE=25
MODE=NORMAL
或者转换为设备接口需要的结构:
{
"device": "Device_A",
"command": "SET_STATE",
"parameters": {
"power": "ON",
"mode": "NORMAL"
}
}
DeviceRenderer 的具体输出取决于设备接口规范。
可以包括:
Device
├── Sensor
├── Controller
├── Terminal
├── Display
├── Industrial Device
└── System Interface
但需要保持一个重要边界:
DeviceRenderer
↓
生成设备表现/接口数据
DeviceAdapter
↓
发送到设备
Device
↓
实际执行
所以:
Renderer ≠ Device Control
Renderer 只负责表现转换。
7. Renderer Interface
为了让不同 Renderer 可以被 SATE 统一管理,可以定义 Renderer Interface。
基本接口:
interface RendererInterface
{
public function render($expression, $template = null);
public function supports($type);
public function getName();
}
例如 WebRenderer:
class WebRenderer implements RendererInterface
{
public function render($expression, $template = null)
{
return $this->renderHtml($expression, $template);
}
public function supports($type)
{
return $type === 'WEB';
}
public function getName()
{
return 'WebRenderer';
}
protected function renderHtml($expression, $template)
{
return '';
}
}
ApiRenderer:
class ApiRenderer implements RendererInterface
{
public function render($expression, $template = null)
{
return json_encode($expression);
}
public function supports($type)
{
return $type === 'API';
}
public function getName()
{
return 'ApiRenderer';
}
}
这样 Renderer 就具有统一入口:
RendererInterface
│
├── WebRenderer
├── UiRenderer
├── ApiRenderer
└── DeviceRenderer
以后增加:
XmlRenderer
TextRenderer
ConsoleRenderer
FileRenderer
也不需要改变 Renderer 的基本体系。
8. Renderer Manager
当系统存在多个 Renderer 时,需要 Renderer Manager 负责管理和选择 Renderer。
基本结构:
RendererManager
{
renderers
register()
remove()
get()
find()
render()
}
例如:
class RendererManager
{
protected $renderers = array();
public function register(RendererInterface $renderer)
{
$this->renderers[$renderer->getName()] = $renderer;
}
public function get($name)
{
if (!isset($this->renderers[$name])) {
return null;
}
return $this->renderers[$name];
}
public function render($rendererName, $expression, $template = null)
{
$renderer = $this->get($rendererName);
if (!$renderer) {
return null;
}
return $renderer->render($expression, $template);
}
}
注册:
$manager = new RendererManager();
$manager->register(new WebRenderer());
$manager->register(new ApiRenderer());
调用:
$result = $manager->render(
'WebRenderer',
$expression,
$template
);
或者:
$result = $manager->render(
'ApiRenderer',
$expression
);
Renderer Manager 的职责是:
Renderer 注册
↓
Renderer 查找
↓
Renderer 选择
↓
Renderer 执行
↓
Rendered Result
它不负责:
认知
推理
决策
学习
记忆
9. Renderer 示例
下面使用一个完整的表现案例。
假设 ICAI 已经完成:
Perception
↓
Cognition
↓
Understanding
↓
Memory
↓
Reasoning
↓
Decision
↓
Behavior
↓
Action
↓
ActionResult
ActionResult:
ActionResult
{
action_id: 1001,
state: "SUCCESS",
output: {
product: "Electric Toothbrush",
quantity: 100,
status: "created"
}
}
形成 Expression:
Expression
{
expression_id: 2001,
type: "RESULT",
target: "external",
data: {
product: "Electric Toothbrush",
quantity: 100,
status: "created"
}
}
选择 WebRenderer:
Expression
↓
WebRenderer
↓
HTML
结果:
<div class="result">
<h2>Order Result</h2>
<p>Product: Electric Toothbrush</p>
<p>Quantity: 100</p>
<p>Status: created</p>
</div>
选择 ApiRenderer:
Expression
↓
ApiRenderer
↓
JSON
结果:
{
"product": "Electric Toothbrush",
"quantity": 100,
"status": "created"
}
选择 UiRenderer:
Expression
↓
UiRenderer
↓
UI Structure
结果:
OrderResult
{
component: "ResultPanel",
children: [
{
component: "Product",
value: "Electric Toothbrush"
},
{
component: "Quantity",
value: 100
},
{
component: "Status",
value: "created"
}
]
}
选择 DeviceRenderer:
Expression
↓
DeviceRenderer
↓
Device Representation
结果:
RESULT
PRODUCT=Electric Toothbrush
QUANTITY=100
STATUS=CREATED
因此,同一个 Expression 可以拥有不同表现:
┌── WebRenderer ─── HTML
│
Expression ─────────┼── UiRenderer ──── UI
│
├── ApiRenderer ─── JSON/XML
│
└── DeviceRenderer ─ Device Data
而这些 Renderer 都可以由 RendererManager 统一管理。
核心模型
第61章可以把 Renderer 放在 SATE 中的这个位置:
ICAI
↓
Expression
↓
SATE
↓
Template
↓
Renderer
↓
Rendered Result
↓
Adapter
↓
External Environment
其中:
Expression = 表现什么
Template = 按什么结构表现
Renderer = 转换成什么表现形式
Adapter = 输出到哪里
例如:
Expression
↓
Template
↓
WebRenderer
↓
HTML
↓
WebAdapter
↓
Browser
或者:
Expression
↓
Template
↓
ApiRenderer
↓
JSON
↓
ApiAdapter
↓
External System
再或者:
Expression
↓
Template
↓
DeviceRenderer
↓
Device Data
↓
DeviceAdapter
↓
Device
核心定义
Renderer 是 SATE 中负责将 Expression 按照 Template 所定义的结构转换为具体表现形式的组件。WebRenderer、UiRenderer、ApiRenderer、DeviceRenderer 等 Renderer 面向不同表现环境,但共同遵循统一的 Renderer Interface,并由 Renderer Manager 进行注册、选择和执行。
最终形成:
Expression
↓
Template
↓
Renderer
↓
Rendered Result
↓
Adapter
↓
Output
这也进一步明确了 Renderer 与 Adapter 的边界:Renderer 负责“表现成什么”,Adapter 负责“输出到哪里”。