第八章:节点关系图的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

TEST(ReactionTest, TestSelfDependency) {
auto a = reaction::var(1);
auto dsA = reaction::calc([](int aa) { return aa; }, a);

EXPECT_THROW(dsA.reset([&]() { return a() + dsA(); }), std::runtime_error);
}

TEST(ReactionTest, TestCycleDependency) {
auto a = reaction::var(1);
auto b = reaction::var(2);
auto c = reaction::var(3);

auto dsA = reaction::calc([](int bb) { return bb; }, b);

auto dsB = reaction::calc([](int cc) { return cc; }, c);

auto dsC = reaction::calc([](int aa) { return aa; }, a);

dsA.reset([&]() { return b() + dsB(); });

dsB.reset([&]() { return c() * dsC(); });

EXPECT_THROW(dsC.reset([&]() { return a() - dsA(); }), std::runtime_error);
}

TEST(ReactionTest, TestRepeatDependency) {
// ds → A, ds → a, A → a
auto a = reaction::var(1).setName("a");
auto b = reaction::var(2).setName("b");

int triggerCount = 0;
auto dsA = reaction::calc([&]() { return a() + b(); }).setName("dsA");

auto dsB = reaction::calc([&]() {++triggerCount; return a() + dsA(); }).setName("dsB");

triggerCount = 0;
a.value(2);
EXPECT_EQ(triggerCount, 1);
EXPECT_EQ(dsB.get(), 6);
}

TEST(ReactionTest, TestRepeatDependency2) {
// ds → A, ds → B, ds → C, A → a, B → a
int triggerCount = 0;
auto a = reaction::var(1).setName("a");
auto A = reaction::calc([&]() { return a() + 1; }).setName("A");
auto B = reaction::calc([&]() { return a() + 2; }).setName("B");
auto C = reaction::calc([&]() { return 5; }).setName("C");
auto ds = reaction::calc([&]() { ++triggerCount; return A() + B() + C(); }).setName("ds");

triggerCount = 0;
a.value(2);
EXPECT_EQ(triggerCount, 1);
EXPECT_EQ(ds.get(), 12);
}

TEST(ReactionTest, TestRepeatDependency3) {
// ds → A, ds → B, A → A1, A1 → A2, A2 → a, B → B1, B1 → a
auto a = reaction::var(1).setName("a");
auto b = reaction::var(1).setName("b");

int triggerCount = 0;
auto A2 = reaction::calc([&]() { return a() * 2; }).setName("A2");
auto A1 = reaction::calc([&]() { return A2() + 1; }).setName("A1");
auto A = reaction::calc([&]() { return A1() - 1; }).setName("A");

auto B1 = reaction::calc([&]() { return a() - 1; }).setName("B1");
auto B = reaction::calc([&]() { return B1() + 1; }).setName("B");

auto ds = reaction::calc([&]() { ++triggerCount; return A() + B(); }).setName("ds");
triggerCount = 0;
a.value(2);
EXPECT_EQ(triggerCount, 1);
EXPECT_EQ(ds.get(), 6);
}

1. 系统架构图

1
2
3
4
5
6
7
8
9
10
%% 系统整体架构图
graph TD
A[ObserverNode] -->|注册| B(ObserverGraph)
A -->|绑定字段| C(FieldGraph)
B -->|管理| D[节点关系网络]
C -->|存储| E[字段-节点映射表]

style A fill:#f9f,stroke:#333
style B fill:#bbf,stroke:#333
style C fill:#bfb,stroke:#333

2. 核心数据结构图解

2.1 节点关系存储结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
%% 数据结构关系图
classDiagram
class ObserverGraph{
+m_observerList: Map<NodePtr, ObserverSet>
+m_dependentList: Map<NodePtr, DependentSet>
+m_repeatList: Map<NodePtr, RepeatCountMap>
+m_nameList: Map<NodePtr, String>
+addObserver()
+checkCycle()
+closeNode()
}

class ObserverNode{
-m_observers: NodeSet
-m_repeats: NodeMap
+valueChanged()
+notify()
}

ObserverGraph "1" --> "*" ObserverNode

2.2 实际内存结构示意图

1
2
3
4
5
6
7
8
9
+---------------------+
| ObserverGraph |
+---------------------+
| m_observerList |--> [NodeA: {NodeB, NodeC}]
| | [NodeB: {NodeD}]
| m_dependentList |--> [NodeB: {NodeA}]
| | [NodeC: {NodeA}]
| m_repeatList |--> [NodeD: {NodeA:2}]
+---------------------+

3. 关键流程详解

3.1 添加观察者流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
%% 添加观察者序列图
sequenceDiagram
participant User
participant SourceNode
participant ObserverGraph
participant TargetNode

User->>SourceNode: updateObservers(TargetNode)
SourceNode->>ObserverGraph: addObserver(Source, Target)
ObserverGraph->>ObserverGraph: 检查自观察
alt 自观察
ObserverGraph-->>SourceNode: 返回错误
else
ObserverGraph->>ObserverGraph: DFS检查循环依赖
alt 存在循环
ObserverGraph-->>SourceNode: 返回错误
else
ObserverGraph->>ObserverGraph: 检查重复依赖路径
ObserverGraph->>TargetNode: 添加到m_observers
ObserverGraph->>SourceNode: 添加到m_dependentList
ObserverGraph-->>SourceNode: 返回成功
end
end

3.2 节点通知流程

1
2
3
4
5
6
7
8
9
%% 节点通知流程图
graph LR
A[节点值变更] --> B[调用valueChanged]
B --> C{是否有重复依赖?}
C -->|是| D[加入重复列表]
C -->|否| E[立即通知]
D --> F[最后批量通知重复节点]
E --> G[遍历观察者链]
G --> H[触发下游更新]

4. 典型场景图示

4.1 正常观察链

1
2
3
4
5
6
%% 正常观察关系图
graph LR
A[数据节点] --> B[视图组件1]
A --> C[视图组件2]
B --> D[聚合视图]
C --> D

4.2 循环依赖检测

1
2
3
4
5
6
7
8
%% 循环依赖示例图
graph TD
A --> B
B --> C
C --> A
style A stroke:#f00,stroke-width:2px
style B stroke:#f00,stroke-width:2px
style C stroke:#f00,stroke-width:2px

4.3 重复依赖处理

1
2
3
4
5
6
%% 重复依赖示例图
graph LR
ds --> A
A --> a
ds --> a

1
2
3
4
5
6
7
%% 重复依赖示例图
graph LR
ds --> A
ds --> B
A --> a
B --> a

1
2
3
4
5
6
7
8
9
10
%% 重复依赖示例图
graph LR
ds --> A
ds --> B
A --> A1
A1 --> A2
A2 --> a
B --> B1
B1 --> a

5. 状态转换图

1
2
3
4
5
6
7
8
9
10
11
12
13
%% 节点生命周期状态图
stateDiagram-v2
[*] --> Created
Created --> Active: addNode
Active --> Observing: addObserver
Observing --> Closed: closeNode
Closed --> [*]

state Observing {
[*] --> Normal
Normal --> HasRepeats: 检测到重复依赖
HasRepeats --> Normal: 重复计数清零
}

6. 性能优化要点

  1. 依赖检查优化

    1
    2
    3
    4
    5
    6
    [DFS优化策略]
    ┌───────────────┐ ┌───────────────┐
    │ 临时添加边 │───>│ 执行DFS检查 │
    └───────────────┘ └───────────────┘
    ▲ │
    └──────────────────┘
  2. 批量通知机制

    1
    2
    3
    4
    5
    6
    普通通知路径: 节点 → 直接观察者
    ┌───────────────────────────────────────┐
    │ 重复依赖处理路径: │
    │ 1. 收集所有重复节点 │
    │ 2. 主通知流程完成后批量触发 │
    └───────────────────────────────────────┘

7. 异常处理图示

1
2
3
4
5
6
7
8
9
%% 错误处理流程图
graph TD
A[操作请求] --> B{是否有效节点?}
B -->|否| C[返回无效节点错误]
B -->|是| D{是否自观察?}
D -->|是| E[返回自观察错误]
D -->|否| F{是否循环依赖?}
F -->|是| G[返回循环依赖错误]
F -->|否| H[执行操作]