<table class="PHP">
<tr class="li1"><td class="ln"><pre class="de1">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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 解决问题的根本 思想必须转换成习惯 构建一套完整的思想体系是开发能力成熟的标志 ——《简单之美》(前言) “成功的软件项目就是那些提交产物达到或超出客户的预期的项目,而且开发过程符合时间和费用上的要求,结果在面对变化和调整时有弹性。” ——《面向对象分析与设计》(第版)P236 术语介绍 ——引用《Spring 技术手册》林信良 非侵入性 No intrusive 框架的目标之一是非侵入性(No intrusive) 组件可以直接拿到另一个应用或框架之中使用 增加组件的可重用性(Reusability) 容器(Container) 管理对象的生成、资源取得、销毁等生命周期 建立对象与对象之间的依赖关系 启动容器后,所有对象直接取用,不用编写任何一行代码来产生对象,或是建立对象之间的依赖关系。 IoC 控制反转 Inversion of Control 依赖关系的转移 依赖抽象而非实践 DI 依赖注入 Dependency Injection 不必自己在代码中维护对象的依赖 容器自动根据配置,将依赖注入指定对象 AOP Aspectoriented programming 面向方面编程 无需修改任何一行程序代码,将功能加入至原先的应用程序中,也可以在不修改任何程序的情况下移除。 分层 表现层:提供服务,显示信息。 领域层:逻辑,系统中真正的核心。 数据源层:与数据库、消息系统、事务管理器及其它软件包通信。 ——《企业应用架构模式》P14 代码演示IoC 假设应用程序有储存需求,若直接在高层的应用程序中调用低层模块API,导致应用程序对低层模块产生依赖。 Business __construct FloppyWriter save FloppyWriter saveToFloppy Business 假设程序要移植到另一个平台,而该平台使用USB磁盘作为存储介质,则这个程序无法直接重用,必须加以修改才行。本例由于低层变化导致高层也跟着变化,不好的设计。 正如前方提到的 控制反转 Inversion of Control 依赖关系的转移 依赖抽象而非实践 程序不应该依赖于具体的实现,而是要依赖抽像的接口。请看代码演示 IDeviceWriter saveToDevice Business setWriter save FloppyWriter IDeviceWriter saveToDevice UsbDiskWriter IDeviceWriter saveToDevice Business UsbDiskWriter FloppyWriter 控制权从实际的FloppyWriter转移到了抽象的IDeviceWriter接口上,让Business依赖于IDeviceWriter接口,且FloppyWriter、UsbDiskWriter也依赖于IDeviceWriter接口。 这就是IoC,面对变化,高层不用修改一行代码,不再依赖低层,而是依赖注入,这就引出了DI。 比较实用的注入方式有三种: Setter injection 使用setter方法 Constructor injection 使用构造函数 Property Injection 直接设置属性 事实上不管有多少种方法,都是IoC思想的实现而已,上面的代码演示的是Setter方式的注入。 依赖注入容器 Dependency Injection Container 管理应用程序中的『全局』对象(包括实例化、处理依赖关系)。 可以延时加载对象(仅用到时才创建对象)。 促进编写可重用、可测试和松耦合的代码。 理解了IoC和DI之后,就引发了另一个问题,引用Phalcon文档描述如下: 如果这个组件有很多依赖, 我们需要创建多个参数的setter方法来传递依赖关系,或者建立一个多个参数的构造函数来传递它们,另外在使用组件前还要每次都创建依赖,这让我们的代码像这样不易维护 注册表中查找 Connection Session FileSystem Filter Selector 函数 SomeComponent