-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
819 lines (711 loc) · 217 KB
/
Copy pathsearch.xml
File metadata and controls
819 lines (711 loc) · 217 KB
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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Express</title>
<url>/post/d7c881ac.html</url>
<content><![CDATA[<h2 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h2><p>这里直接使用<code>app.get</code>来处理请求</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> express = <span class="built_in">require</span>(<span class="string">"source/_posts/Express"</span>);</span><br><span class="line"><span class="keyword">var</span> app = <span class="title function_">express</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// respond with "hello world" when a GET request is made to the homepage</span></span><br><span class="line">app.<span class="title function_">get</span>(<span class="string">"/"</span>, <span class="keyword">function</span> (<span class="params">req, res</span>) {</span><br><span class="line"> res.<span class="title function_">send</span>(<span class="string">"hello world"</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<h2 id="项目实例"><a href="#项目实例" class="headerlink" title="项目实例"></a>项目实例</h2><p><code>usersController.js</code></p>
<blockquote>
<p>暴露函数</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span>.<span class="property">register</span> = <span class="function">(<span class="params">req, res, next</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">body</span>);</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p><code>UserRoutes.js</code></p>
<blockquote>
<p>中间件 处理其中一类的请求</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> { register } = <span class="built_in">require</span>(<span class="string">"../controllers/usersController"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment">路由对象在Express.js中通常被视为一种特殊类型的中间件。当你将路由对象挂载到特定的路径上时,它可以拦截和处理该路径下的请求,类似于其他中间件。路由对象允许你组织和处理特定路径下的请求,因此在这种意义上它可以被认为是中间件的一种。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">"source/_posts/Express"</span>).<span class="property">Router</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 设置请求路径及回调函数</span></span><br><span class="line">router.<span class="title function_">post</span>(<span class="string">"/register"</span>, register);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = router;</span><br></pre></td></tr></table></figure>
<p><code>index.js</code></p>
<blockquote>
<p>中间件 处理其中一类的请求 挂载 userRoutes 到/api/auth 路径下</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">"source/_posts/Express"</span>);</span><br><span class="line"><span class="keyword">const</span> cors = <span class="built_in">require</span>(<span class="string">"cors"</span>);</span><br><span class="line"><span class="comment">// 与mongodb进行交互</span></span><br><span class="line"><span class="keyword">const</span> mongoose = <span class="built_in">require</span>(<span class="string">"mongoose"</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> userRoutes = <span class="built_in">require</span>(<span class="string">"./routes/UserRoutes"</span>);</span><br><span class="line"><span class="keyword">const</span> app = <span class="title function_">express</span>();</span><br><span class="line"><span class="built_in">require</span>(<span class="string">"dotenv"</span>).<span class="title function_">config</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// *中间件</span></span><br><span class="line">app.<span class="title function_">use</span>(<span class="title function_">cors</span>());</span><br><span class="line">app.<span class="title function_">use</span>(express.<span class="title function_">json</span>());</span><br><span class="line"></span><br><span class="line"><span class="comment">// *挂载userRoutes到api/auth路径下</span></span><br><span class="line">app.<span class="title function_">use</span>(<span class="string">"api/auth"</span>, userRoutes);</span><br><span class="line"></span><br><span class="line">mongoose</span><br><span class="line"> .<span class="title function_">connect</span>(process.<span class="property">env</span>.<span class="property">MONGO_URL</span>, {</span><br><span class="line"> <span class="attr">useNewUrlParser</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">useUnifiedTopology</span>: <span class="literal">true</span>,</span><br><span class="line"> })</span><br><span class="line"> .<span class="title function_">then</span>(<span class="function">() =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"DB Connection Success"</span>);</span><br><span class="line"> })</span><br><span class="line"> .<span class="title function_">catch</span>(<span class="function">(<span class="params">error</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">"Error occured"</span>, error.<span class="property">message</span>);</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> server = app.<span class="title function_">listen</span>(process.<span class="property">env</span>.<span class="property">PORT</span>, <span class="function">() =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`Server Started on Port <span class="subst">${process.env.PORT}</span>`</span>);</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>node</tag>
</tags>
</entry>
<entry>
<title>Git Commit</title>
<url>/post/70316f9e.html</url>
<content><![CDATA[<h3 id="commit-message-格式"><a href="#commit-message-格式" class="headerlink" title="commit message 格式"></a><strong>commit message 格式</strong></h3><p><code><type>(<scope>): <subject></code></p>
<h3 id="type"><a href="#type" class="headerlink" title="type"></a><strong>type</strong></h3><ul>
<li><p>feat:新功能(feature)。</p>
</li>
<li><p>fix/to:修复 bug,可以是 QA 发现的 BUG,也可以是研发自己发现的 BUG。</p>
</li>
<li><p>docs:文档(documentation)。</p>
</li>
<li><p>style:格式(不影响代码运行的变动)。</p>
</li>
<li><p>refactor:重构(即不是新增功能,也不是修改 bug 的代码变动)。</p>
</li>
<li><p>perf:优化相关,比如提升性能、体验。</p>
</li>
<li><p>test:增加测试。</p>
</li>
<li><p>chore:构建过程或辅助工具的变动。</p>
</li>
<li><p>revert:回滚到上一个版本。</p>
</li>
<li><p>merge:代码合并。</p>
</li>
<li><p>sync:同步主线或分支的 Bug。</p>
</li>
</ul>
<h3 id="scope-可选"><a href="#scope-可选" class="headerlink" title="scope(可选)"></a><strong>scope(可选)</strong></h3><p>scope 用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。</p>
<p>例如在 Angular,可以是 location,browser,compile,compile,rootScope, ngHref,ngClick,ngView 等。如果你的修改影响了不止一个 scope,你可以使用*代替。</p>
<h3 id="subject-必须"><a href="#subject-必须" class="headerlink" title="subject(必须)"></a><strong>subject(必须)</strong></h3><p>subject 是 commit 目的的简短描述,不超过 50 个字符。</p>
<ul>
<li><p>结尾不加句号或其他标点符号。</p>
</li>
<li><p>根据以上规范 git commit message 将是如下的格式:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">fix(DAO):用户查询缺少username属性</span><br><span class="line">feat(Controller):用户查询接口开发</span><br></pre></td></tr></table></figure></li>
</ul>
]]></content>
<tags>
<tag>git</tag>
</tags>
</entry>
<entry>
<title>Promise</title>
<url>/post/54b11a0c.html</url>
<content><![CDATA[<h1 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h1><h2 id="Promise-的基本使用"><a href="#Promise-的基本使用" class="headerlink" title="Promise 的基本使用"></a>Promise 的基本使用</h2><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {});</span><br></pre></td></tr></table></figure>
<ul>
<li><p>Promise 接受一个函数作为参数</p>
</li>
<li><p>在参数函数中有两个参数</p>
<ul>
<li><p>resolve: 成功函数</p>
</li>
<li><p>reject: 失败函数</p>
</li>
</ul>
</li>
</ul>
<h3 id="1-Promise-的状态"><a href="#1-Promise-的状态" class="headerlink" title="1) Promise 的状态"></a>1) Promise 的状态</h3><p>第一种状态:<code> pending</code></p>
<p>第二种状态: <code>fulfilled</code></p>
<p>第三种状态: <code>rejected</code></p>
<h3 id="2-Promise-状态的改变"><a href="#2-Promise-状态的改变" class="headerlink" title="2) Promise 状态的改变"></a>2) Promise 状态的改变</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="comment">// resolve(): 调用函数, 使当前Promise对象的状态改成fulfilled</span></span><br><span class="line"> <span class="title function_">resolve</span>();</span><br><span class="line">});</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">dir</span>(p); <span class="comment">// fulfilled</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="comment">// resolve(): 调用函数, 使当前Promise对象的状态改成fulfilled</span></span><br><span class="line"> <span class="comment">// reject(): 调用函数, 使当前Promise对象的状态改成rejected</span></span><br><span class="line"> <span class="comment">// resolve();</span></span><br><span class="line"> <span class="title function_">reject</span>();</span><br><span class="line">});</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">dir</span>(p);</span><br></pre></td></tr></table></figure>
<ul>
<li>resolve(): 调用函数, 使当前 Promise 对象的状态改成<code>fulfilled</code></li>
<li>reject(): 调用函数,使当前 Promise 对象状态改成<code>rejected</code></li>
</ul>
<h3 id="3-Promise-的结果"><a href="#3-Promise-的结果" class="headerlink" title="3) Promise 的结果"></a>3) Promise 的结果</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="comment">// 通过调用 resolve,传递参数,改变 当前Promise对象的结果</span></span><br><span class="line"> <span class="title function_">resolve</span>(<span class="string">"成功的结果"</span>);</span><br><span class="line"> <span class="comment">// resolve();</span></span><br><span class="line"> <span class="comment">// reject("失败的结果")</span></span><br><span class="line">});</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">dir</span>(p);</span><br></pre></td></tr></table></figure>
<h2 id="Promise-的方法"><a href="#Promise-的方法" class="headerlink" title="Promise 的方法"></a>Promise 的方法</h2><h3 id="1-then-方法"><a href="#1-then-方法" class="headerlink" title="1) then 方法"></a>1) then 方法</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="comment">// 通过调用 resolve,传递参数,改变 当前Promise对象的结果</span></span><br><span class="line"> <span class="comment">// resolve(123);</span></span><br><span class="line"> <span class="title function_">reject</span>(<span class="string">"失败的结果"</span>);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">//then方法函数</span></span><br><span class="line"><span class="comment">// - 参数</span></span><br><span class="line"><span class="comment">// 两个参数都是函数</span></span><br><span class="line"><span class="comment">// 返回值: 是一个Promise对象</span></span><br><span class="line">p.<span class="title function_">then</span>(</span><br><span class="line"> <span class="function">(<span class="params">value</span>) =></span> {</span><br><span class="line"> <span class="comment">//当Promise的状态使fulfilled时执行</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"成功的回调"</span>, value);</span><br><span class="line"> },</span><br><span class="line"> <span class="function">(<span class="params">err</span>) =></span> {</span><br><span class="line"> <span class="comment">// 当Promise的状态时rejected时, 执行</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败时调用"</span>, err);</span><br><span class="line"> }</span><br><span class="line">);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">dir</span>(p);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>在 then 方法中,通过 return 将返回的 Promise 实例改为 fulfilled 状态</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 如果Promise的状态不改变,then里的方法不会执行</span></span><br><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {});</span><br><span class="line"><span class="keyword">const</span> t = p.<span class="title function_">then</span>(</span><br><span class="line"> <span class="function">(<span class="params">value</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"成功"</span>);</span><br><span class="line"> <span class="comment">// 使用return可以将t实例的状态改为fulfilled</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">123</span>;</span><br><span class="line"> },</span><br><span class="line"> <span class="function">(<span class="params">reason</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败"</span>);</span><br><span class="line"> }</span><br><span class="line">);</span><br><span class="line">t.<span class="title function_">then</span>(</span><br><span class="line"> <span class="function">(<span class="params">value</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"成功2"</span>, value);</span><br><span class="line"> },</span><br><span class="line"> <span class="function">(<span class="params">reason</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败2"</span>);</span><br><span class="line"> }</span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>在 then 方法中,出现代码错误,将返回的 Promise 实例改为 rejected 状态</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 如果Promise的状态改变,then里的方法不会执行</span></span><br><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"><span class="keyword">const</span> t = p.<span class="property">then</span>.(<span class="function">(<span class="params">value</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"成功"</span>)</span><br><span class="line"> <span class="comment">// 使用return可以将t实例的状态改为fulfilled</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">123</span></span><br><span class="line">},<span class="function">(<span class="params">reason</span>) =></span> {</span><br><span class="line"> <span class="comment">// 如果这里代码出错,会将t实例的状态改为rejected</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败"</span>)</span><br><span class="line">})</span><br><span class="line">t.<span class="property">then</span>.(<span class="function">(<span class="params">value</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"成功2"</span>,value)</span><br><span class="line">},<span class="function">(<span class="params">reason</span>) =></span> {</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败2"</span>)</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<h3 id="2-catch-方法"><a href="#2-catch-方法" class="headerlink" title="2) catch 方法"></a>2) catch 方法</h3><blockquote>
<p>示例</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> <span class="comment">// reject()</span></span><br><span class="line"> <span class="comment">// console.log(a)</span></span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">"出错了"</span>);</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">// 思考: catch中的参数函数在什么时候被执行</span></span><br><span class="line"><span class="comment">// 1. 当Promise的状态改为rejcted.被执行</span></span><br><span class="line"><span class="comment">// 2. 当Promise执行过程出现代码错误时,被执行</span></span><br><span class="line">p.<span class="title function_">catch</span>((<span class="function"><span class="params">reason</span> =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">"失败"</span>, reason)</span><br><span class="line">})</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(p);</span><br></pre></td></tr></table></figure>
<h2 id="async-和-await"><a href="#async-和-await" class="headerlink" title="async 和 await"></a>async 和 await</h2><h2 id="1-async-函数"><a href="#1-async-函数" class="headerlink" title="1) async 函数"></a>1) async 函数</h2><ol>
<li>函数的返回值为 promise 对象</li>
<li>promise 对象的结果由 async 函数执行的返回值决定</li>
</ol>
<p>示例</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">main</span>(<span class="params"></span>){</span><br><span class="line"> <span class="comment">// 1.如果返回值是一个非Promise类型的数据</span></span><br><span class="line"> <span class="comment">// return 一个字符串 数字 布尔值等都是成功的Promise对象</span></span><br><span class="line"> <span class="comment">// 2. 如果返回的时一个Promise对象</span></span><br><span class="line"> <span class="comment">// return new Promise((resolve, reject) => {</span></span><br><span class="line"> <span class="comment">// resolve("OK") 返回的是成功Promise对象,状态值:[[PromiseState]]:"fulfilled"</span></span><br><span class="line"> <span class="comment">// reject("Err") 返回的是失败Promise对象,状态值:[[PromiseState]]:"rejected"</span></span><br><span class="line"> <span class="comment">// 3. 抛出异常</span></span><br><span class="line"> <span class="keyword">throw</span> <span class="string">"oh No"</span> <span class="comment">// 状态值:[[PromiseState]]:"rejected",结果是抛出的值</span></span><br><span class="line">})</span><br><span class="line">}</span><br><span class="line"><span class="keyword">let</span> result = <span class="title function_">main</span>();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(result);</span><br></pre></td></tr></table></figure>
<p>返回值是一个 Promise 对象</p>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/2934759/1615302593894-e1a59c34-08ff-4241-8eba-5512b1718bde.png" alt="img"></p>
<h2 id="2-await-表达式"><a href="#2-await-表达式" class="headerlink" title="2) await 表达式"></a>2) await 表达式</h2><ol>
<li>await 右侧的表达式一般为 promise 对象, 但也可以是其它的值</li>
<li>如果表达式是 promise 对象, await 返回的是 promise 成功的值</li>
<li>如果表达式是其它值, 直接将此值作为 await 的返回值</li>
</ol>
<p>注意</p>
<ol>
<li>await 必须写在 async 函数中, 但 async 函数中可以没有 await</li>
<li>如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理</li>
</ol>
<h2 id="3-async-和-await-结合"><a href="#3-async-和-await-结合" class="headerlink" title="3) async 和 await 结合"></a>3) async 和 await 结合</h2><p>示例</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">"fs"</span>);</span><br><span class="line"><span class="keyword">const</span> util = <span class="built_in">require</span>(<span class="string">"util"</span>);</span><br><span class="line"><span class="keyword">const</span> mineReadFile = util.<span class="title function_">promisify</span>(fs.<span class="property">readFile</span>);<span class="comment">// promisify转换为Promise形态的函数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">main</span>(<span class="params"></span>){</span><br><span class="line"> <span class="comment">// 捕获处理</span></span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> <span class="comment">// 读取第一个文件的内容</span></span><br><span class="line"> <span class="keyword">let</span> data1 = <span class="keyword">await</span> <span class="title function_">mineReadFile</span>(<span class="string">"./resource/1.html"</span>);</span><br><span class="line"> <span class="keyword">let</span> data2 = <span class="keyword">await</span> <span class="title function_">mineReadFile</span>(<span class="string">"./resource/2.html"</span>);</span><br><span class="line"> <span class="keyword">let</span> data3 = <span class="keyword">await</span> <span class="title function_">mineReadFile</span>(<span class="string">"./resource/3.html"</span>);</span><br><span class="line"> }<span class="keyword">catch</span>(e){</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(e):</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>javaScript</tag>
</tags>
</entry>
<entry>
<title>WELCOME TO MY BLOG 🍾 🪅 🥂 🎉</title>
<url>/post/4a17b156.html</url>
<content><![CDATA[]]></content>
</entry>
<entry>
<title>WebSocket</title>
<url>/post/c793072c.html</url>
<content><![CDATA[<h1 id="Web-SOCKET"><a href="#Web-SOCKET" class="headerlink" title="Web SOCKET"></a>Web SOCKET</h1><h2 id="websocket-介绍"><a href="#websocket-介绍" class="headerlink" title="websocket 介绍"></a>websocket 介绍</h2><p>web socket 是一种全双工通讯的网络技术,属于应用层协议,基于 TCP 传输协议,并复用了 HTTP 的握手通道</p>
<p>是一种长连接,不需要频繁的链接断开</p>
<h3 id="websocket-数据帧格式"><a href="#websocket-数据帧格式" class="headerlink" title="websocket 数据帧格式"></a>websocket 数据帧格式</h3><blockquote>
<p>单位是 bit 如 FIN RSV 都占据 1bit opcode 占据 4bit</p>
</blockquote>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309061628568.png" alt="image-20230906162803200"></p>
<ul>
<li><p>FIN 1BIT 标记数据是否发送到最后一位</p>
<p>如果是消息的最后一个分片,则返回的是 1 否则返回 0</p>
</li>
<li><p>OPCODE 4BIT</p>
<p>==9 10 用于心跳监测==</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309062225696.png" alt="image-20230906222522624"></p>
</li>
<li><p>MASK(掩码)</p>
<ul>
<li>客户端发送消息到服务端 掩码为 1</li>
<li>服务端发送消息到客户端 掩码为 0</li>
</ul>
</li>
<li><p>PAYLOAD(数据载荷长度)</p>
<p>说明传输的数据的字节 根据 Payload length 的长度 判断后续字节的作用</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309071030759.png" alt="image-20230907103055654"></p>
<p><code>Buffer</code>字节数组</p>
<ul>
<li><p>大端序:高位放在低地址先读,按顺序读取</p>
</li>
<li><p>小端序:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309071121351.png" alt="image-20230907112108233"></p>
<p><strong>输出为 256 1</strong></p>
</li>
</ul>
</li>
<li><p>Masking-Key</p>
<p>0 或 4 字节(32 位)所有从客户端传送到服务端的数据帧,数据载荷都进行了掩<br>码操作,Mask 为 1,且携带了 4 字节的 Masking-key。如果 Mask 为 0,则没有 Masking-key。<br>载荷数的长度,不包括 mask key 的长度</p>
</li>
</ul>
<h2 id="websocket-建立链接过程"><a href="#websocket-建立链接过程" class="headerlink" title="websocket 建立链接过程"></a>websocket 建立链接过程</h2><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309062208820.png" alt=" "></p>
<p><strong>客户端请求头及请求相应状态</strong>:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309062212586.png" alt="image-20230906221244548"></p>
<p><strong>服务端响应</strong></p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309062214054.png" alt="image-20230906221421998"></p>
<p>其中请求中的<code>Sec-Websocket-Key</code>用于验证链接是否合法</p>
<p>状态码中的 101 代表协议切换</p>
<h2 id="客户端发送消息到客户端"><a href="#客户端发送消息到客户端" class="headerlink" title="客户端发送消息到客户端"></a>客户端发送消息到客户端</h2><h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><blockquote>
<p>客户端代码</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE <span class="keyword">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span></span></span><br><span class="line"><span class="tag"> <span class="attr">name</span>=<span class="string">"viewport"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1.0"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Document<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span></span></span><br><span class="line"><span class="tag"> <span class="attr">type</span>=<span class="string">"text"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">id</span>=<span class="string">"text"</span> /></span></span><br><span class="line"> <span class="tag"><<span class="name">button</span> <span class="attr">onclick</span>=<span class="string">"send()"</span>></span>send<span class="tag"></<span class="name">button</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span>></span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">let</span> text = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">"text"</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 在浏览器链接服务器</span></span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">let</span> soket = <span class="keyword">new</span> <span class="title class_">WebSocket</span>(<span class="string">"ws://localhost:8889"</span>);</span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 当链接打开或建立后,触发回调</span></span></span><br><span class="line"><span class="language-javascript"> soket.<span class="property">onopen</span> = <span class="keyword">function</span> (<span class="params"></span>) {</span></span><br><span class="line"><span class="language-javascript"> soket.<span class="title function_">send</span>(<span class="string">"hello server"</span>);</span></span><br><span class="line"><span class="language-javascript"> };</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// 服务器端给客户端发送消息时 可以通过soket.onmessage接受 存储于event中</span></span></span><br><span class="line"><span class="language-javascript"> soket.<span class="property">onmessage</span> = <span class="keyword">function</span> (<span class="params">event</span>) {</span></span><br><span class="line"><span class="language-javascript"> <span class="comment">// soket.send(event.data);</span></span></span><br><span class="line"><span class="language-javascript"> <span class="variable language_">console</span>.<span class="title function_">log</span>(event.<span class="property">data</span>);</span></span><br><span class="line"><span class="language-javascript"> };</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">function</span> <span class="title function_">send</span>(<span class="params"></span>) {</span></span><br><span class="line"><span class="language-javascript"> <span class="keyword">let</span> value = text.<span class="property">value</span>;</span></span><br><span class="line"><span class="language-javascript"> text.<span class="property">value</span> = <span class="string">""</span>;</span></span><br><span class="line"><span class="language-javascript"> soket.<span class="title function_">send</span>(value);</span></span><br><span class="line"><span class="language-javascript"> }</span></span><br><span class="line"><span class="language-javascript"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>服务端代码</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> { <span class="title class_">Server</span> } = <span class="built_in">require</span>(<span class="string">"ws"</span>);</span><br><span class="line"><span class="keyword">const</span> wsServer = <span class="keyword">new</span> <span class="title class_">Server</span>({ <span class="attr">port</span>: <span class="number">8889</span> });</span><br><span class="line"><span class="comment">//wsServer 服务器</span></span><br><span class="line"><span class="comment">//socket 套接字 类似于打电话的手机</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//"connection"监听客户端过来的链接</span></span><br><span class="line">wsServer.<span class="title function_">on</span>(<span class="string">"connection"</span>, <span class="function">(<span class="params">socket</span>) =></span> {</span><br><span class="line"> <span class="comment">//“message"监听当前链接的客户端发来的消息</span></span><br><span class="line"> socket.<span class="title function_">on</span>(<span class="string">"message"</span>, <span class="function">(<span class="params">message</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(message.<span class="title function_">toLocaleString</span>());</span><br><span class="line"> socket.<span class="title function_">send</span>(message);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<h3 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h3><ol>
<li><code>let soket = new WebSocket("ws://localhost:8889") </code>浏览器链接服务器</li>
<li><code> soket.send("hello server");</code>客户端向服务器发消息 “hello server”</li>
<li><code>socket.on("message"</code>)服务端监听到消息并触发回调,向客户端发送消息</li>
<li><code>soket.onmessage</code>客户端监听到服务端的相应,触发回调打印</li>
</ol>
]]></content>
<categories>
<category>网络通信</category>
</categories>
<tags>
<tag>websocket</tag>
</tags>
</entry>
<entry>
<title>css布局</title>
<url>/post/5a252ba9.html</url>
<content><![CDATA[<h3 id="display"><a href="#display" class="headerlink" title="display"></a>display</h3><p> <strong>block</strong> (块元素):</p>
<ul>
<li>块元素会在页面中独占行(自上向下垂直排列)</li>
<li>默认宽度是父元素的全部(会把父元素撑满)</li>
<li>默认高度是被内容撑开(子元素)</li>
</ul>
<p>一般用于其他标签的容器,常用的块级元素包括 div p h1-h6 hr ul ol li dl dd dt form</p>
<p> <strong>inline</strong> (行内元素):</p>
<ul>
<li>行内元素不会独占页面的一行, 只占自身的大小</li>
<li>行内元素在页面中左向右水平排列,如果一行之中不能容纳下所有的行内元则元素 会换到第二行继续自左向右排列 (书写习惯一致)</li>
<li>行内元素的默认宽度和高度都是被内容撑开。</li>
</ul>
<p>常用的行内元素包括span a</p>
<p>行内元素的盒模型</p>
<ul>
<li>行内元素不支持设置宽度和高度</li>
<li>行内元素可以设置padding,但是垂直方向padding不会影响页面的布局 ;</li>
<li>行内元素可以设置border.垂直方向的border不会影响页面的布局;</li>
<li>行内元素可以设置margin,垂直方向的margin不会影响布局</li>
</ul>
<p> <strong>inline-block</strong> (行内元素):支持宽高,自左向右排列,不独占一行<br>,常用的行内块元素包括img textarea input</p>
<p><strong>none</strong> :<br>一些特殊元素的默认 display 值是none,例如script, display:none被 JavaScript 用来在不删除元素的情况下隐藏或显示元素。<br>它和visibility属性不一样。把display设置成 none元素不会占据它本来应该显示的空间,但是设置成 visibility: hidden;还会占据空间。</p>
<h3 id="position"><a href="#position" class="headerlink" title="position"></a>position</h3><p><strong>static</strong> : 静态,默认值,文档流</p>
<p><strong>relative</strong> :<br>相对定位不脱离文档流,对周围元素的位置没有任何影响<br>如果相对定位不写偏移属性或者偏移量为0,效果与没写定位一样<br>相对自已原来位置做偏移原来的位子不会被占着(不脱离文档流)<br>使用场合<br>①类似于margin(margin挤开,相对定位覆盖其他元素),做自身位置的微调<br>②作为绝对定位的祖先级已定位属性(子绝父相,此处多不写偏移属性)<br>偏移属性的特点: 上下冲突,以top为准 ; 左右冲突,以left为准</p>
<p><strong>fixed</strong> :<br>将元素固定在页面上某个位置,不会随着滚动条滚动,变化位置</p>
<p>一直固定在可视区域 , 一个固定定位(position属性的值为fixed)元素会相对于视窗来定位,这意味着即便页面滚动,它还是会停留在相同的位置。和relative一样,top、right、bottom和left属性都可用。一个固定定位元素不会保留它原本在页面应有的空隙,即之后添加的元素会占用他之前的位置。</p>
<p><strong>absolute</strong> :<br>绝对定位脱离文档流<br>1.没有已定位的祖先级元素,相对body左上角偏移</p>
<p>2.相对于,离自己最近的,已定位的,祖先级元素的左上角做偏移</p>
<p>注意:最适合把祖先级变成已定位元素的样式,relative</p>
<h3 id="float"><a href="#float" class="headerlink" title="float"></a>float</h3><p>通过浮动可以使一个元素 向其父元素的左侧或右侧移动 使用float 属性来设置于元素的浮动<br>可选值: none 默认值,元素不浮动<br>left 元素向左浮动<br>right 元素向右浮动<br>注意,元素设置浮动以后,水平布局的等式便不需要强制成立<br>元素设置浮动以后,会完全从文档流中脱离,不再占用文档流的位置, 所以元素 下边的还在文档流中的元素会自动向上移动</p>
<p>浮动的特点:</p>
<ol>
<li>浮动元素会完全脱离文档流,不再占据文档流中的位置</li>
<li>设置浮动以后元素会向父元素的左侧或右侧移动,</li>
<li>浮动元素默认不会从父元素中移出</li>
<li>浮动元素向左或向右移动时,不会超过它前边的其他浮动元素</li>
<li>如果浮动元素的上边是一个没有浮动的块元素,则浮动元素无法上移</li>
<li>浮动元素不会超过它上边的浮动的兄弟元素,最多最多就是和它一样高</li>
</ol>
<p>浮动目前来讲它的主要作用就是让页面中的元素可以水平排列,<br>通过浮动可以制作一些水平方向的布局<br>浮动元素不会盖住文字,文字会自动环绕在浮动元素的周围,<br>所以我们可以利用浮动来设置文字环绕图片的效果<br>元素设置浮动以后,将会从文档流中脱离,从文档流中脱离后,元素的一些特点也会发变化<br>脱离文档流的特点:</p>
<p>块元素:</p>
<ul>
<li>块元素不在独占页面的一行</li>
<li>脱离文档流以后,块元素的宽度和高度默认都被内容撑开</li>
</ul>
<p>行内元素:</p>
<ul>
<li>行内元素脱离文档流以后会变成块元素(可设置宽高),特点和块元素一样</li>
<li>脱离文档流以后,不需要再区分块和行内了</li>
</ul>
<p><strong>clear</strong> :<br>float属性被用于控制浮动。即元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用clear属性,clear属性指定元素两侧不能出现浮动元素。</p>
<p><strong>清除浮动</strong><br>在一个div中放一张图片,有时候图片会超出div的范围,这个时候我们需要这样做,给div加上此属性</p>
<p><code>.clearfix { overflow: auto; }</code></p>
<h3 id="flex"><a href="#flex" class="headerlink" title="flex"></a>flex</h3><p>容器的属性</p>
<ul>
<li>flex-direction(主轴方向)</li>
<li>flex-wrap(是否换行)</li>
<li>flex-flow(主轴方向与是否换行的简写形式)</li>
<li>justify-content(在长度上的排列方式)</li>
<li>align-items(在宽度上的排列方式)</li>
<li>align-content(行间距)</li>
</ul>
<p><strong>flex-direction</strong> :<br>属性决定主轴的方向(即项目的排列方向)<br>, 可以理解为元素排列的起点在哪里,沿哪个方向排列。把显示屏比喻为一张纸的话,该属性决定了第一个字在哪个角开始写以及第一行字写的方向</p>
<p>row(默认值):主轴为水平方向,起点在左端。</p>
<p>row-reverse:主轴为水平方向,起点在右端。</p>
<p>column:主轴为垂直方向,起点在上沿。</p>
<p>column-reverse:主轴为垂直方向,起点在下沿。</p>
<p><strong>flex-wrap</strong> :<br>默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,如果一条轴线排不下,如何换行, 把显示屏比喻为一张纸的话,该属性决定了一行字写完以后换行不换行(假设是字可以一直缩小,不换行且继续新增的话,字会背挤的越来越小)</p>
<p>nowrap(默认):不换行。</p>
<p>wrap:换行,第一行在上方。</p>
<p>wrap-reverse:换行,第一行在下方。</p>
<p><strong>flex-flow</strong></p>
<p>flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。</p>
<p><strong>justify-content</strong> :<br>justify-content属性定义了项目在主轴上的对齐方式,可以理解为在显示屏的长度这个方向上元素的排列方式 , 把显示屏比喻为一张纸的话,该属性决定了在这一行的字的排列方式</p>
<p>flex-start(默认值):左对齐</p>
<p>flex-end:右对齐</p>
<p>center: 居中</p>
<p>space-between:两端对齐,项目之间的间隔都相等。</p>
<p>space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。</p>
<p><strong>align-items</strong> :<br>align-items属性定义项目在交叉轴上如何对齐<br>可以理解为在显示屏的宽度上元素的排列方式,把显示屏比喻为一张纸的话,该属性决定第一行字距离纸的边距距离</p>
<p>flex-start:交叉轴的起点对齐。</p>
<p>flex-end:交叉轴的终点对齐。</p>
<p>center:交叉轴的中点对齐。</p>
<p>baseline: 项目的第一行文字的基线对齐。</p>
<p>stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。</p>
<p><strong>align-content</strong> :<br>align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用, 可以理解为行与行之间的间隔距离,把显示屏比喻为一张纸的话,该属性决定第行间距</p>
<p>flex-start:与交叉轴的起点对齐。</p>
<p>flex-end:与交叉轴的终点对齐。</p>
<p>center:与交叉轴的中点对齐。</p>
<p>space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。</p>
<p>space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。</p>
<p>stretch(默认值):轴线占满整个交叉轴。(平均铺满显示器)</p>
]]></content>
<tags>
<tag>css</tag>
</tags>
</entry>
<entry>
<title>函数闭包</title>
<url>/post/87bab44d.html</url>
<content><![CDATA[<h2 id="什么是闭包"><a href="#什么是闭包" class="headerlink" title="什么是闭包"></a>什么是闭包</h2><p>有权访问另一个函数作用域中的变量的函数,就是闭包。</p>
<p>这是一种闭包</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">animal</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> name = <span class="string">"dog"</span>;</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">getName</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(name);</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_">getName</span>();</span><br><span class="line">}</span><br><span class="line"><span class="title function_">animal</span>();</span><br></pre></td></tr></table></figure>
<p>这也是一种闭包</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> name = <span class="string">"cat"</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getName</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(name);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>name 定义在全局作用域中,getName 在内部输出找不到自己定义的值,因此向外寻找,输出 getName,是一个隐性的闭包。</p>
<h3 id="一个例子记住"><a href="#一个例子记住" class="headerlink" title="一个例子记住"></a>一个例子记住</h3><blockquote>
<p>函数在创建时,会保存所有父变量对象到其中的[scope]中。函数激活时,会将自身的活动对象添加到作用链的前端</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> data = [];</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">3</span>; i++) {</span><br><span class="line"> data[i] = <span class="keyword">function</span> (<span class="params"></span>) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(i);</span><br><span class="line"> };</span><br><span class="line">}</span><br><span class="line"><span class="comment">// data中的每个元素的scope均为[global.vo]</span></span><br><span class="line"></span><br><span class="line">data[<span class="number">0</span>]();</span><br><span class="line">data[<span class="number">1</span>]();</span><br><span class="line">data[<span class="number">2</span>]();</span><br></pre></td></tr></table></figure>
<p>输出均为3</p>
<p>当执行到 data[0] 函数之前,此时全局上下文的 VO 为:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">globalContext = {</span><br><span class="line"> <span class="attr">VO</span>: {</span><br><span class="line"> <span class="attr">data</span>: [...],</span><br><span class="line"> <span class="attr">i</span>: <span class="number">3</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>当执行 data[0] 函数的时候,data[0] 函数的作用域链为:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">data[<span class="number">0</span>]<span class="title class_">Context</span> = {</span><br><span class="line"> <span class="title class_">Scope</span>: [<span class="variable constant_">AO</span>, globalContext.<span class="property">VO</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>data[0]Context 的 AO 并没有 i 值,所以会从 globalContext.VO 中查找,i 为 3,所以打印的结果就是 3。</p>
<p>data[1] 和 data[2] 是一样的道理。</p>
<p>所以让我们改成闭包看看:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> data = [];</span><br><span class="line"><span class="comment">// 此处需注意 需要将i传递给匿名函数 如果不进行传递 匿名函数的ao中就不会有i这个变量 最后就会去全局变量对象中寻找i</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">3</span>; i++) {</span><br><span class="line"> data[i] = (<span class="keyword">function</span> (<span class="params">i</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">function</span>(<span class="params"></span>){</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(i);</span><br><span class="line"> }</span><br><span class="line"> })(i);</span><br><span class="line">}</span><br><span class="line"><span class="comment">// data中的每个元素的scope均为[匿名函数.ao,global.vo]</span></span><br><span class="line"></span><br><span class="line">data[<span class="number">0</span>]();</span><br><span class="line">data[<span class="number">1</span>]();</span><br><span class="line">data[<span class="number">2</span>]();</span><br></pre></td></tr></table></figure>
<p>当执行到 data[0] 函数之前,此时全局上下文的 VO 为:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">globalContext = {</span><br><span class="line"> VO: {</span><br><span class="line"> data: [...],</span><br><span class="line"> i: 3</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>跟没改之前一模一样。</p>
<p>当执行 data[0] 函数的时候,data[0] 函数的作用域链发生了改变:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">data[0]Context = {</span><br><span class="line"> Scope: [AO, 匿名函数Context.AO globalContext.VO]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>匿名函数执行上下文的AO为:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>
<p>data[0]Context 的 AO 并没有 i 值,所以会沿着作用域链从匿名函数 Context.AO 中查找,这时候就会找 i 为 0,找到了就不会往 globalContext.VO 中查找了,即使 globalContext.VO 也有 i 的值(值为3),所以打印的结果就是0。</p>
<p>data[1] 和 data[2] 是一样的道理。</p>
<p>文章参考<a href="https://github.com/mqyqingfeng/Blog/issues/9%EF%BC%8C%E5%AF%B9%E5%85%B6%E8%BF%9B%E8%A1%8C%E4%BA%86%E6%B3%A8%E9%87%8A%E6%96%B9%E4%BE%BF%E5%AD%A6%E4%B9%A0">https://github.com/mqyqingfeng/Blog/issues/9,对其进行了注释方便学习</a></p>
]]></content>
<categories>
<category>JavaScript 深入学习</category>
</categories>
<tags>
<tag>closure</tag>
</tags>
</entry>
<entry>
<title>原型及原型链</title>
<url>/post/7be7e7cb.html</url>
<content><![CDATA[<h1 id="原型和原型链"><a href="#原型和原型链" class="headerlink" title="原型和原型链"></a>原型和原型链</h1><h2 id="构造函数创建对象"><a href="#构造函数创建对象" class="headerlink" title="构造函数创建对象"></a>构造函数创建对象</h2><p>我们先使用构造函数创建一个对象:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"><span class="keyword">const</span> person = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line">person.<span class="property">name</span> = <span class="string">"ameee9"</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">name</span>); <span class="comment">// ameee9</span></span><br></pre></td></tr></table></figure>
<h2 id="prototype"><a href="#prototype" class="headerlink" title="prototype"></a>prototype</h2><p>每个函数都有一个 prototype 属性,就是我们经常在各种例子中看到的那个 prototype ,比如:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"><span class="comment">// prototype是函数才会有的属性</span></span><br><span class="line"><span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">name</span> = <span class="string">"ameee9"</span>;</span><br><span class="line"><span class="keyword">var</span> person1 = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"><span class="keyword">var</span> person2 = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person1.<span class="property">name</span>); <span class="comment">// ameee9</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person2.<span class="property">name</span>); <span class="comment">// ame ee9</span></span><br></pre></td></tr></table></figure>
<p>函数的 <code>prototype 属性</code>指向了一个对象,这个对象正是调用该构造函数而创建的<strong>实例</strong>的原型,也就是这个例子中的 person1 和 person2 的原型。</p>
<p>每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型”继承”属性。</p>
<p>构造函数和实例原型之间的关系:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309202302859.png" alt="1"></p>
<p>在这张图中我们用 Object.prototype 表示实例原型。</p>
<h2 id="proto"><a href="#proto" class="headerlink" title="_proto_"></a><code>_proto_</code></h2><p>这是每一个 JavaScript 对象(除了 null )都具有的一个属性,叫<code>_proto_</code>,这个属性会指向该对象的原型。</p>
<p>为了证明这一点,我们可以在火狐或者谷歌中输入:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"><span class="keyword">var</span> person = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"><span class="comment">// 使用 __proto__ 是有争议且不被鼓励的。它的存在和确切行为仅作为遗留特性被标准化,以确保 Web 兼容性,但它存在一些安全问题和隐患。</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">__proto__</span> === <span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>); <span class="comment">// true</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Object</span>.<span class="title function_">getPrototypeOf</span>(person) === <span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<p>新的关系图:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309202311901.png" alt="2"></p>
<p>既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?</p>
<h2 id="constructor-NaN"><a href="#constructor-NaN" class="headerlink" title="constructor"></a>constructor</h2><p>指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,这就要讲到第三个属性:constructor,每个原型都有一个 constructor 属性指向关联的构造函数。</p>
<p>为了验证这一点,我们可以尝试:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Person</span> === <span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<p>所以再更新下关系图:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309202314771.png" alt="2"></p>
<p>综上可以得到:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> person = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">__proto__</span> == <span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>); <span class="comment">// true</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span> == <span class="title class_">Person</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<p>了解了构造函数、实例原型、和实例之间的关系,接下来我们讲讲实例和原型的关系:</p>
<h2 id="实例与原型"><a href="#实例与原型" class="headerlink" title="实例与原型"></a>实例与原型</h2><p>当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。</p>
<p>举个例子:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"></span><br><span class="line"><span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">name</span> = <span class="string">"prototype"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> person = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"></span><br><span class="line">person.<span class="property">name</span> = <span class="string">"ameee9"</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">name</span>); <span class="comment">// ameee9</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span> person.<span class="property">name</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">name</span>); <span class="comment">// prototype</span></span><br></pre></td></tr></table></figure>
<p>在这个例子中,我们给实例对象 person 添加了 name 属性,当我们打印 person.name 的时候,结果自然为 ameee9。</p>
<p>但是当我们删除了 person 的 name 属性时,读取 person.name,从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.<code>__proto__</code> ,也就是 Person.prototype 中查找,幸运的是我们找到了 name 属性,结果为 prototype</p>
<p>但是万一还没有找到呢?原型的原型又是什么呢?</p>
<h2 id="原型的原型"><a href="#原型的原型" class="headerlink" title="原型的原型"></a>原型的原型</h2><p>原型也是一个对象,既然是对象,我们就可以用最原始的方式创建它,那就是:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">obj.<span class="property">name</span> = <span class="string">"ameee9"</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(obj.<span class="property">name</span>); <span class="comment">// ameee9</span></span><br></pre></td></tr></table></figure>
<p>其实原型对象就是通过 Object 构造函数生成的,结合之前所讲,实例的 <strong>_ proto _</strong> 指向构造函数的 prototype ,所以我们再更新下关系图:</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202309202336407.png" alt="3"></p>
<h2 id="原型链"><a href="#原型链" class="headerlink" title="原型链"></a>原型链</h2><p>那 Object.prototype 的原型呢?</p>
<p>null,我们可以打印:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">console.log(Object.prototype.__proto__ === null) // true</span><br></pre></td></tr></table></figure>
<blockquote>
<p>null 表示“没有对象”,即该处不应该有值。</p>
</blockquote>
<p>所以 Object.prototype.<strong>proto</strong> 的值为 null 跟 Object.prototype 没有原型,其实表达了一个意思。</p>
<p>所以查找属性的时候查到 Object.prototype 就可以停止查找了。</p>
<p>最后一张关系图也可以更新为:</p>
<p><a href="https://camo.githubusercontent.com/9a69b0f03116884e80cf566f8542cf014a4dd043fce6ce030d615040461f4e5a/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f6d717971696e6766656e672f426c6f672f496d616765732f70726f746f74797065352e706e67"><img src="https://camo.githubusercontent.com/9a69b0f03116884e80cf566f8542cf014a4dd043fce6ce030d615040461f4e5a/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f6d717971696e6766656e672f426c6f672f496d616765732f70726f746f74797065352e706e67" alt="原型链示意图"></a></p>
<p>顺便还要说一下,图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。</p>
<h2 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h2><h3 id="constructor"><a href="#constructor" class="headerlink" title="constructor"></a>constructor</h3><p>首先是 constructor 属性,我们看个例子:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>) {}</span><br><span class="line"><span class="keyword">var</span> person = <span class="keyword">new</span> <span class="title class_">Person</span>();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(person.<span class="property">constructor</span> === <span class="title class_">Person</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<p>当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到 constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">person.<span class="property">constructor</span> === <span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">constructor</span>;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>来自 <a href="https://github.com/mqyqingfeng/Blog/issues/2">JavaScript 深入之从原型到原型链</a></p>
</blockquote>
]]></content>
<categories>
<category>JavaScript 深入学习</category>
</categories>
<tags>
<tag>原型链</tag>
</tags>
</entry>
<entry>
<title>执行上下文栈</title>
<url>/post/dec4cd8f.html</url>
<content><![CDATA[<h2 id="一个思考题"><a href="#一个思考题" class="headerlink" title="一个思考题"></a>一个思考题</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> scope = <span class="string">"global scope"</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">checkscope</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">var</span> scope = <span class="string">"local scope"</span>;</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">f</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">return</span> scope;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">f</span>();</span><br><span class="line">}</span><br><span class="line"><span class="title function_">checkscope</span>();</span><br><span class="line"><span class="keyword">var</span> scope = <span class="string">"global scope"</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">checkscope</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">var</span> scope = <span class="string">"local scope"</span>;</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">f</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">return</span> scope;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> f;</span><br><span class="line">}</span><br><span class="line"><span class="title function_">checkscope</span>()();</span><br></pre></td></tr></table></figure>
<p>两段代码执行的结果均输出<code>local scope</code></p>
<blockquote>
<p>JavaScript 采用的是词法作用域,<strong>函数的作用域基于函数创建的位置</strong></p>
<p>JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。</p>
</blockquote>
<p>两端代码的压栈顺序</p>
<p>答案就是执行上下文栈的变化不一样。</p>
<p>第一段代码:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">push</span>(<checkscope> functionContext);</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">push</span>(<f> functionContext);</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">pop</span>();</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">pop</span>();</span><br></pre></td></tr></table></figure>
<blockquote>
<p>第一代码在执行 <code>checkscope()</code> 时,内部的 <code>f()</code> 也在函数内被执行。因此有连续两次的压栈操作。</p>
</blockquote>
<p>让我们模拟第二段代码:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">push</span>(<checkscope> functionContext);</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">pop</span>();</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">push</span>(<f> functionContext);</span><br><span class="line"><span class="title class_">ECStack</span>.<span class="title function_">pop</span>();</span><br></pre></td></tr></table></figure>
<blockquote>
<p>在第二段代码中,<code>checkscope()</code> 返回了函数 <code>f</code>,然后在返回的函数 <code>f</code> 上执行了另一次 <code>()</code>,这导致了两次执行上下文的压栈和出栈。</p>
</blockquote>
<h2 id="作用域"><a href="#作用域" class="headerlink" title="作用域"></a>作用域</h2><p>代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:</p>
<ul>
<li>最==外层函数==和==在最外层函数外面定义的变量==拥有全局作用域</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> outVariable = <span class="string">"我是最外层变量"</span>; <span class="comment">//最外层变量</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">outFun</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="comment">//最外层函数</span></span><br><span class="line"> <span class="keyword">var</span> inVariable = <span class="string">"内层变量"</span>;</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">innerFun</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="comment">//内层函数</span></span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(inVariable);</span><br><span class="line"> }</span><br><span class="line"> <span class="title function_">innerFun</span>();</span><br><span class="line">}</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(outVariable); <span class="comment">//我是最外层变量</span></span><br><span class="line"><span class="title function_">outFun</span>(); <span class="comment">//内层变量</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(inVariable); <span class="comment">//inVariable is not defined</span></span><br><span class="line"><span class="title function_">innerFun</span>(); <span class="comment">//innerFun is not defined</span></span><br></pre></td></tr></table></figure>
<ul>
<li>所有末定义直接赋值的变量自动声明为拥有全局作用域</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">outFun2</span>(<span class="params"></span>) {</span><br><span class="line"> variable = <span class="string">"未定义直接赋值的变量"</span>;</span><br><span class="line"> <span class="keyword">var</span> inVariable2 = <span class="string">"内层变量2"</span>;</span><br><span class="line">}</span><br><span class="line"><span class="title function_">outFun2</span>(); <span class="comment">//要先执行这个函数,否则根本不知道里面是啥</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(variable); <span class="comment">//未定义直接赋值的变量</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(inVariable2); <span class="comment">//inVariable2 is not defined</span></span><br></pre></td></tr></table></figure>
<ul>
<li>所有 window 对象的属性拥有全局作用域</li>
</ul>
<h2 id="执行上下文栈的流程"><a href="#执行上下文栈的流程" class="headerlink" title="执行上下文栈的流程"></a>执行上下文栈的流程</h2><ol>
<li><p>压入全局上下文</p>
</li>
<li><p>当执行一个到函数时,会创建一个函数执行上下文(Function Execution Context),并将其压入执行上下文栈。这个函数执行上下文包括了函数的参数,以及在函数内部声明的变量和函数。</p>
<p>在 JavaScript 中,存在全局执行上下文(Global Execution Context)和函数执行上下文(Function Execution Context)。全局执行上下文在浏览器开始读取脚本时创建,只有一个。而函数执行上下文每当函数被调用时都会创建。</p>
<p>每个执行上下文都有一个关联的变量对象(Variable Object),它包含了在上下文中定义的所有变量和函数。在函数执行上下文中,活动对象(Activation Object)扮演了变量对象的角色,它在函数执行上下文被推入执行上下文栈时创建,包含了函数的参数,以及在函数内部声明的所有变量和函数。</p>
</li>
<li><p><strong>执行函数执行上下文</strong></p>
<p>执行上下文的代码会分成两个阶段进行处理:分析和执行,我们也可以叫做:</p>
<ul>
<li><p>进入执行上下文</p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202402291724151.png" alt="image-20240229172408618"></p>
</li>
</ul>
</li>
</ol>
]]></content>
<categories>
<category>JavaScript 深入学习</category>
</categories>
<tags>
<tag>上下文</tag>
</tags>
</entry>
<entry>
<title>文章配置</title>
<url>/post/dc78123f.html</url>
<content><![CDATA[<h2 id="表头配置"><a href="#表头配置" class="headerlink" title="表头配置"></a>表头配置</h2><figure class="highlight markdown"><table><tr><td class="code"><pre><span class="line">categories:</span><br><span class="line">description:</span><br><span class="line">top<span class="emphasis">_img: ''</span></span><br></pre></td></tr></table></figure>
<h2 id="更新时间"><a href="#更新时间" class="headerlink" title="更新时间"></a>更新时间</h2><figure class="highlight markdown"><table><tr><td class="code"><pre><span class="line">updated:</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>config</tag>
</tags>
</entry>
<entry>
<title>浏览器如何保持登录</title>
<url>/post/e190ec45.html</url>
<content><![CDATA[<h2 id="Cookie"><a href="#Cookie" class="headerlink" title="Cookie"></a>Cookie</h2><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202401061432265.png" alt="image-20240106143226574"></p>
<h2 id="Session"><a href="#Session" class="headerlink" title="Session"></a>Session</h2><figure class="highlight java"><table><tr><td class="code"><pre><span class="line">request.getSession().setAttribute(USER_LOGIN_STATE, user);</span><br></pre></td></tr></table></figure>
<p>通过 <code>request.getSession().setAttribute(USER_LOGIN_STATE, user);</code> 设置属性时,实际上将用户登录状态信息安全地存储在服务器端的 <code>HttpSession</code> 对象中。该 <code>HttpSession</code> 对象在服务器上被创建和管理(所有的请求都会被存储,由serverlet来管理),其中的属性数据被保存在服务器端。</p>
<p>接着,通过将 <code>JSESSIONID</code> 发送给客户端,并在后续的请求中通过 Cookie 携带回来,服务器能够根据这个 <code>JSESSIONID</code> 找到相应的 <code>HttpSession</code> 对象。通过 <code>getAttribute</code> 方法,我们可以从这个 <code>HttpSession</code> 中安全地读取属性信息,如用户登录状态。</p>
<h2 id="Token"><a href="#Token" class="headerlink" title="Token"></a>Token</h2><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202401061502119.png" alt="image-20240106150249050"></p>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/readme/202401061503827.png" alt="image-20240106150331724"></p>
]]></content>
<categories>
<category>网络通信</category>
</categories>
<tags>
<tag>cookie</tag>
<tag>session</tag>
<tag>token</tag>
</tags>
</entry>
<entry>
<title>设计模式</title>
<url>/post/364ea8cc.html</url>
<content><![CDATA[<h1 id="设计模式"><a href="#设计模式" class="headerlink" title="设计模式"></a>设计模式</h1><h2 id="策略模式"><a href="#策略模式" class="headerlink" title="策略模式"></a>策略模式</h2><h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a><strong>介绍</strong></h3><p>定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户变化。</p>
<h3 id="结构"><a href="#结构" class="headerlink" title="结构"></a><strong>结构</strong></h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230526150814561.png" alt="image-20230526150814561"></p>
<h3 id="角色"><a href="#角色" class="headerlink" title="角色"></a><strong>角色</strong></h3><ul>
<li>Context(环境类)</li>
<li>Strategy(抽象策略类)</li>
<li>Concrete Strategy(具体策略类)</li>
</ul>
<h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a><strong>实现</strong></h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象策略类代码</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Strategy</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">algorithm</span><span class="params">()</span>; <span class="comment">//声明抽象算法</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//具体策略类代码</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcreteStrategyA</span> <span class="keyword">extends</span> <span class="title class_">Strategy</span> {</span><br><span class="line"> <span class="comment">//算法的具体实现</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">algorithm</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//算法A</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//环境类代码</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Context</span> {</span><br><span class="line"> <span class="keyword">private</span> Strategy strategy; <span class="comment">//维持一个对抽象策略类的引用</span></span><br><span class="line"> <span class="comment">//注入策略对象</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setStrategy</span><span class="params">(Strategy strategy)</span> {</span><br><span class="line"> <span class="built_in">this</span>.strategy= strategy;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//调用策略类中的算法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">algorithm</span><span class="params">()</span> {</span><br><span class="line"> strategy.algorithm();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//客户端代码片段</span></span><br><span class="line">……</span><br><span class="line"><span class="type">Context</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Context</span>();</span><br><span class="line">Strategy strategy;</span><br><span class="line">strategy = <span class="keyword">new</span> <span class="title class_">ConcreteStrategyA</span>(); <span class="comment">//可在运行时指定类型,通过配置文件和反射机制实现</span></span><br><span class="line">context.setStrategy(strategy);</span><br><span class="line">context.algorithm();</span><br><span class="line">……</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h2 id="装饰器模式"><a href="#装饰器模式" class="headerlink" title="装饰器模式"></a>装饰器模式</h2><h3 id="介绍-1"><a href="#介绍-1" class="headerlink" title="介绍"></a>介绍</h3><p>在不改变一个对象本身功能的基础上给对象增加额外的新行为,引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩展原有类的功能</p>
<h3 id="结构-1"><a href="#结构-1" class="headerlink" title="结构"></a><strong>结构</strong></h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230526161910156.png" alt="image-20230526161910156"></p>
<h3 id="角色-1"><a href="#角色-1" class="headerlink" title="角色"></a><strong>角色</strong></h3><ul>
<li><p>Component(抽象构件)</p>
</li>
<li><p>Concrete Component(具体构件)</p>
</li>
<li><p>Decorator(抽象装饰类)</p>
</li>
<li><p>Concrete Decorator(具体装饰类)</p>
</li>
</ul>
<h3 id="实现-1"><a href="#实现-1" class="headerlink" title="实现"></a><strong>实现</strong></h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象构件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Component</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体构件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ListBox</span> <span class="keyword">extends</span> <span class="title class_">Component</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示列表框!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">--------------------------------------------------------------------------</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体构件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TextBox</span> <span class="keyword">extends</span> <span class="title class_">Component</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示文本框!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象装饰类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ComponentDecorator</span> <span class="keyword">extends</span> <span class="title class_">Component</span> {</span><br><span class="line"> <span class="comment">//维持对抽象构件类型对象的引用</span></span><br><span class="line"> <span class="keyword">private</span> Component component;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//注入抽象构件类型的对象</span></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ComponentDecorator</span><span class="params">(Component component)</span> {</span><br><span class="line"> <span class="built_in">this</span>.component = component;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> component.display();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体装饰类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BlackBorderDecorator</span> <span class="keyword">extends</span> <span class="title class_">ComponentDecorator</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">BlackBorderDecorator</span><span class="params">(Component component)</span> {</span><br><span class="line"> <span class="built_in">super</span>(component);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">this</span>.setBlackBorder();</span><br><span class="line"> <span class="built_in">super</span>.display();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setBlackBorder</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"为构件增加黑色边框!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="观察者模式"><a href="#观察者模式" class="headerlink" title="观察者模式"></a>观察者模式</h2><h3 id="介绍-2"><a href="#介绍-2" class="headerlink" title="介绍"></a>介绍</h3><p>定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。</p>
<h3 id="结构-2"><a href="#结构-2" class="headerlink" title="结构"></a><strong>结构</strong></h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230528120615051.png" alt="image-20230528120615051"></p>
<h3 id="角色-2"><a href="#角色-2" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Subject(目标)</li>
<li>Concrete Subject(具体目标)</li>
<li>Observer(观察者)</li>
<li>Concrete Observer(具体观察者)</li>
</ul>
<h3 id="实现-2"><a href="#实现-2" class="headerlink" title="实现"></a>实现</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//战队控制中心类:抽象目标类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AllyControlCenter</span> {</span><br><span class="line"> <span class="keyword">protected</span> String allyName; <span class="comment">//战队名称</span></span><br><span class="line"> <span class="keyword">protected</span> ArrayList<Observer> players = <span class="keyword">new</span> <span class="title class_">ArrayList</span><Observer>(); <span class="comment">//定义一个集合用于存储战队成员</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAllyName</span><span class="params">(String allyName)</span> {</span><br><span class="line"> <span class="built_in">this</span>.allyName = allyName;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getAllyName</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.allyName;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//注册方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">join</span><span class="params">(Observer obs)</span> {</span><br><span class="line"> System.out.println(obs.getName() + <span class="string">"加入"</span> + <span class="built_in">this</span>.allyName + <span class="string">"战队!"</span>);</span><br><span class="line"> players.add(obs);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//注销方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">quit</span><span class="params">(Observer obs)</span> {</span><br><span class="line"> System.out.println(obs.getName() + <span class="string">"退出"</span> + <span class="built_in">this</span>.allyName + <span class="string">"战队!"</span>);</span><br><span class="line"> players.remove(obs);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//声明抽象通知方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">notifyObserver</span><span class="params">(String name)</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//具体战队控制中心类:具体目标类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConcreteAllyControlCenter</span> <span class="keyword">extends</span> <span class="title class_">AllyControlCenter</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ConcreteAllyControlCenter</span><span class="params">(String allyName)</span> {</span><br><span class="line"> System.out.println(allyName + <span class="string">"战队组建成功!"</span>);</span><br><span class="line"> System.out.println(<span class="string">"----------------------------"</span>);</span><br><span class="line"> <span class="built_in">this</span>.allyName = allyName;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//实现通知方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">notifyObserver</span><span class="params">(String name)</span> {</span><br><span class="line"> System.out.println(<span class="built_in">this</span>.allyName + <span class="string">"战队紧急通知,盟友"</span> + name + <span class="string">"遭受敌人攻击!"</span>);</span><br><span class="line"> <span class="comment">//遍历观察者集合,调用每一个盟友(自己除外)的支援方法</span></span><br><span class="line"> <span class="keyword">for</span>(Object obs : players) {</span><br><span class="line"> <span class="keyword">if</span> (!((Observer)obs).getName().equalsIgnoreCase(name)) {</span><br><span class="line"> ((Observer)obs).help();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象观察类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Observer</span> {</span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">help</span><span class="params">()</span>; <span class="comment">//声明支援盟友方法(响应方法)</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">beAttacked</span><span class="params">(AllyControlCenter acc)</span>; <span class="comment">//声明遭受攻击方法</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//战队成员类:具体观察者类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Player</span> <span class="keyword">implements</span> <span class="title class_">Observer</span> {</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Player</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//支援盟友方法的实现</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">help</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"坚持住,"</span> + <span class="built_in">this</span>.name + <span class="string">"来救你!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//遭受攻击方法的实现,当遭受攻击时将调用战队控制中心类的通知方法notifyObserver()来通知盟友</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">beAttacked</span><span class="params">(AllyControlCenter acc)</span> {</span><br><span class="line"> System.out.println(<span class="built_in">this</span>.name + <span class="string">"被攻击!"</span>);</span><br><span class="line"> acc.notifyObserver(name);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//客户端代码</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String args[])</span> {</span><br><span class="line"> <span class="comment">//定义观察目标对象</span></span><br><span class="line"> AllyControlCenter acc;</span><br><span class="line"> acc = <span class="keyword">new</span> <span class="title class_">ConcreteAllyControlCenter</span>(<span class="string">"金庸群侠"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//定义四个观察者对象</span></span><br><span class="line"> Observer player1,player2,player3,player4,player5;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//注册观察者</span></span><br><span class="line"> player1 = <span class="keyword">new</span> <span class="title class_">Player</span>(<span class="string">"杨过"</span>);</span><br><span class="line"> acc.join(player1);</span><br><span class="line"></span><br><span class="line"> player2 = <span class="keyword">new</span> <span class="title class_">Player</span>(<span class="string">"令狐冲"</span>);</span><br><span class="line"> acc.join(player2);</span><br><span class="line"></span><br><span class="line"> player3 = <span class="keyword">new</span> <span class="title class_">Player</span>(<span class="string">"张无忌"</span>);</span><br><span class="line"> acc.join(player3);</span><br><span class="line"></span><br><span class="line"> player4 = <span class="keyword">new</span> <span class="title class_">Player</span>(<span class="string">"段誉"</span>);</span><br><span class="line"> acc.join(player4);</span><br><span class="line"></span><br><span class="line"> player5 = <span class="keyword">new</span> <span class="title class_">Player</span>(<span class="string">"郭靖"</span>);</span><br><span class="line"> acc.join(player5);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//某成员遭受攻击 调用通知方法</span></span><br><span class="line"> player2.beAttacked(acc);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="适配器模式"><a href="#适配器模式" class="headerlink" title="适配器模式"></a>适配器模式</h2><h3 id="介绍-3"><a href="#介绍-3" class="headerlink" title="介绍"></a>介绍</h3><p>适配器模式是一种结构型设计模式,旨在解决两个不兼容接口之间的兼容性问题。它允许将一个类的接口转换成客户端所期望的另一个接口</p>
<h3 id="结构-3"><a href="#结构-3" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230528124621463.png" alt="image-20230528124621463"></p>
<h3 id="角色-3"><a href="#角色-3" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Target(目标抽象类)</li>
<li>Adapter(适配器类)</li>
<li>Adaptee(适配者类)</li>
</ul>
<h3 id="实现-3"><a href="#实现-3" class="headerlink" title="实现"></a>实现</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//救护车灯类,充当适配者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AmbulanceLamp</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">alarmLamp</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"呈现救护车灯闪烁!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//救护车声音类,充当适配者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AmbulanceSound</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">alarmSound</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"发出救护车声音!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//救护车适配器,充当适配器</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AmbulanceCarAdapter</span> <span class="keyword">extends</span> <span class="title class_">CarController</span> {</span><br><span class="line"> <span class="keyword">private</span> AmbulanceSound sound; <span class="comment">//定义适配者AmbulanceSound对象</span></span><br><span class="line"> <span class="keyword">private</span> AmbulanceLamp lamp; <span class="comment">//定义适配者AmbulanceLamp对象</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">AmbulanceCarAdapter</span><span class="params">()</span> {</span><br><span class="line"> sound = <span class="keyword">new</span> <span class="title class_">AmbulanceSound</span>();</span><br><span class="line"> lamp = <span class="keyword">new</span> <span class="title class_">AmbulanceLamp</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//发出救护车声音</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">phonate</span><span class="params">()</span> {</span><br><span class="line"> sound.alarmSound(); <span class="comment">//调用适配者类AmbulanceSound的方法(类似于转发调用)</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//呈现救护车灯闪烁</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">twinkle</span><span class="params">()</span> {</span><br><span class="line"> lamp.alarmLamp(); <span class="comment">//调用适配者类AmbulanceLamp的方法</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//汽车控制类,充当目标抽象类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">CarController</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">move</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"玩具汽车移动!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">phonate</span><span class="params">()</span>; <span class="comment">//发出声音</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">twinkle</span><span class="params">()</span>; <span class="comment">//灯光闪烁</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="抽象工厂模式"><a href="#抽象工厂模式" class="headerlink" title="抽象工厂模式"></a>抽象工厂模式</h2><h3 id="介绍-4"><a href="#介绍-4" class="headerlink" title="介绍"></a>介绍</h3><p>提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。又称为工具(Kit)模式抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率</p>
<h3 id="结构-4"><a href="#结构-4" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230529121322432.png" alt="image-20230529121322432"></p>
<h3 id="角色-4"><a href="#角色-4" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Abstract Factory(抽象工厂)</li>
<li>Concrete Factory(具体工厂)</li>
<li>Abstract Product(抽象产品)</li>
<li>Concrete Product(具体产品)</li>
</ul>
<h3 id="实现-4"><a href="#实现-4" class="headerlink" title="实现"></a>实现</h3><p><strong>三种抽象产品</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象按钮</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Button</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象边框</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ComboBox</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象文本框</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">TextField</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>抽象工厂</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">SkinFactory</span> {</span><br><span class="line"> <span class="keyword">public</span> Button <span class="title function_">createButton</span><span class="params">()</span>;</span><br><span class="line"> <span class="keyword">public</span> TextField <span class="title function_">createTextField</span><span class="params">()</span>;</span><br><span class="line"> <span class="keyword">public</span> ComboBox <span class="title function_">createComboBox</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>具体产品(部分)</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"> <span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringButton</span> <span class="keyword">implements</span> <span class="title class_">Button</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示浅绿色按钮。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringComboBox</span> <span class="keyword">implements</span> <span class="title class_">ComboBox</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示绿色边框组合框。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SummerButton</span> <span class="keyword">implements</span> <span class="title class_">Button</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示浅蓝色按钮。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SummerComboBox</span> <span class="keyword">implements</span> <span class="title class_">ComboBox</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示蓝色边框组合框。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>具体工厂</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// SpringSkinFactory工厂</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SpringSkinFactory</span> <span class="keyword">implements</span> <span class="title class_">SkinFactory</span> {</span><br><span class="line"> <span class="keyword">public</span> Button <span class="title function_">createButton</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SpringButton</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> TextField <span class="title function_">createTextField</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SpringTextField</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ComboBox <span class="title function_">createComboBox</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SpringComboBox</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// SummerSkinFactory工厂</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SummerSkinFactory</span> <span class="keyword">implements</span> <span class="title class_">SkinFactory</span> {</span><br><span class="line"> <span class="keyword">public</span> Button <span class="title function_">createButton</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SummerButton</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> TextField <span class="title function_">createTextField</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SummerTextField</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> ComboBox <span class="title function_">createComboBox</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">SummerComboBox</span>();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="建造者模式"><a href="#建造者模式" class="headerlink" title="建造者模式"></a>建造者模式</h2><h3 id="介绍-5"><a href="#介绍-5" class="headerlink" title="介绍"></a>介绍</h3><p>将一个复杂对象的==构建与它的表示分离==,使得同样的构建过程可以创建不同的表示。将客户端与包含多个部件的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可关注如何逐步创建一个复杂的对象,不同的建造者定义了不同的创建过程</p>
<h3 id="结构-5"><a href="#结构-5" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230529185109415.png" alt="image-20230529185109415"></p>
<h3 id="角色-5"><a href="#角色-5" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Builder(抽象建造者)</li>
<li>Concrete Builder(具体建造者)</li>
<li>Product(产品)</li>
<li>Director(指挥者)</li>
</ul>
<h3 id="实现-5"><a href="#实现-5" class="headerlink" title="实现"></a>实现</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体角色类(产品)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Actor</span> {</span><br><span class="line"> <span class="keyword">private</span> String type; <span class="comment">//角色类型</span></span><br><span class="line"> <span class="keyword">private</span> String sex; <span class="comment">//性别</span></span><br><span class="line"> <span class="keyword">private</span> String face; <span class="comment">//脸型</span></span><br><span class="line"> <span class="keyword">private</span> String costume; <span class="comment">//服装</span></span><br><span class="line"> <span class="keyword">private</span> String hairstyle; <span class="comment">//发型</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//省略具体的getter setter</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象建造者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">ActorBuilder</span> {</span><br><span class="line"> <span class="keyword">protected</span> <span class="type">Actor</span> <span class="variable">actor</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Actor</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">buildType</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">buildSex</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">buildFace</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">buildCostume</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">buildHairstyle</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//工厂方法,返回一个完整的游戏角色对象</span></span><br><span class="line"> <span class="keyword">public</span> Actor <span class="title function_">createActor</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> actor;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体建造者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AngelBuilder</span> <span class="keyword">extends</span> <span class="title class_">ActorBuilder</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildType</span><span class="params">()</span> {</span><br><span class="line"> actor.setType(<span class="string">"天使"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildSex</span><span class="params">()</span> {</span><br><span class="line"> actor.setSex(<span class="string">"女"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildFace</span><span class="params">()</span> {</span><br><span class="line"> actor.setFace(<span class="string">"漂亮"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildCostume</span><span class="params">()</span> {</span><br><span class="line"> actor.setCostume(<span class="string">"白裙"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">buildHairstyle</span><span class="params">()</span> {</span><br><span class="line"> actor.setHairstyle(<span class="string">"披肩长发"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 指挥者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ActorController</span> {</span><br><span class="line"> <span class="comment">//逐步构建复杂产品对象</span></span><br><span class="line"> <span class="keyword">public</span> Actor <span class="title function_">construct</span><span class="params">(ActorBuilder ab)</span> {</span><br><span class="line"> Actor actor;</span><br><span class="line"> ab.buildType();</span><br><span class="line"> ab.buildSex();</span><br><span class="line"> ab.buildFace();</span><br><span class="line"> ab.buildCostume();</span><br><span class="line"> ab.buildHairstyle();</span><br><span class="line"> actor=ab.createActor();</span><br><span class="line"> <span class="keyword">return</span> actor;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 客户端代码</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String args[])</span> {</span><br><span class="line"> <span class="comment">//针对抽象建造者编程</span></span><br><span class="line"> ActorBuilder ab;</span><br><span class="line"> <span class="comment">//反射生成具体建造者对象</span></span><br><span class="line"> ab = (ActorBuilder)XMLUtil.getBean();</span><br><span class="line"></span><br><span class="line"> <span class="type">ActorController</span> <span class="variable">ac</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ActorController</span>();</span><br><span class="line"> Actor actor;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//通过指挥者创建完整的建造者对象</span></span><br><span class="line"> <span class="comment">//传入具体建造者对象(ActorBuilder 的子类对象)</span></span><br><span class="line"> actor = ac.construct(ab);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="type">String</span> <span class="variable">type</span> <span class="operator">=</span> actor.getType();</span><br><span class="line"> System.out.println(type + <span class="string">"的外观:"</span>);</span><br><span class="line"> System.out.println(<span class="string">"性别:"</span> + actor.getSex());</span><br><span class="line"> System.out.println(<span class="string">"面容:"</span> + actor.getFace());</span><br><span class="line"> System.out.println(<span class="string">"服装:"</span> + actor.getCostume());</span><br><span class="line"> System.out.println(<span class="string">"发型:"</span> + actor.getHairstyle());</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="原型模式"><a href="#原型模式" class="headerlink" title="原型模式"></a>原型模式</h2><h3 id="介绍-6"><a href="#介绍-6" class="headerlink" title="介绍"></a>介绍</h3><p>使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象</p>
<h3 id="结构-6"><a href="#结构-6" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230530091411776.png" alt="image-20230530091411776"></p>
<h3 id="角色-6"><a href="#角色-6" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Prototype(抽象原型类)</li>
<li>Concrete Prototype(具体原型类)</li>
<li>Client(客户类)</li>
</ul>
<h3 id="实现-6"><a href="#实现-6" class="headerlink" title="实现"></a>实现</h3><h4 id="浅拷贝"><a href="#浅拷贝" class="headerlink" title="浅拷贝"></a>浅拷贝</h4><p>(其中的引用对象相同)</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeeklyLog</span> <span class="keyword">implements</span> <span class="title class_">Cloneable</span> {</span><br><span class="line"> <span class="comment">//为了简化设计和实现,假设一份工作周报中只有一个附件对象,实际情况中可以包含多个附件,可以通过List等集合对象来实现</span></span><br><span class="line"> <span class="keyword">private</span> Attachment attachment;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> String date;</span><br><span class="line"> <span class="keyword">private</span> String content;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAttachment</span><span class="params">(Attachment attachment)</span> {</span><br><span class="line"> <span class="built_in">this</span>.attachment = attachment;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDate</span><span class="params">(String date)</span> {</span><br><span class="line"> <span class="built_in">this</span>.date = date;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setContent</span><span class="params">(String content)</span> {</span><br><span class="line"> <span class="built_in">this</span>.content = content;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Attachment <span class="title function_">getAttachment</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.attachment);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.name);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getDate</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.date);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getContent</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.content);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//使用clone()方法实现浅克隆</span></span><br><span class="line"> <span class="keyword">public</span> WeeklyLog <span class="title function_">clone</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> obj = <span class="built_in">super</span>.clone();</span><br><span class="line"> <span class="keyword">return</span> (WeeklyLog) obj;</span><br><span class="line"> } <span class="keyword">catch</span> (CloneNotSupportedException e) {</span><br><span class="line"> System.out.println(<span class="string">"不支持复制!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h4><p>==(序列化与反序列化)==</p>
<p>序列化是将对象转换为字节流的过程,可以将对象保存到文件、传输到网络或在进程之间进行通信。在序列化过程中,对象的状态(即对象的数据)被转换为字节序列,包括对象的字段和相应的数值。序列化后的字节流可以被保存下来或传输给其他地方。</p>
<p>反序列化是将字节流转换为对象的过程,将保存在字节流中的数据重新构造成对象。在反序列化过程中,字节序列被还原为对象的状态,重新创建对象并将保存的数据填充到对象的字段中。</p>
<p>在写入字节流时,对象的所有字段都会被序列化为字节序列。而在读取字节流时,字节序列会被反序列化为一个新的对象,并将保存的数据填充到新对象的字段中。</p>
<p>由于反序列化过程会重新创建对象,因此新对象与原始对象是完全独立的,它们拥有相同的数据但是位于不同的内存位置。这样就实现了深拷贝,保留了对象及其所有引用类型字段的数据,并且不共享同一块内存。</p>
<p>需要注意的是,为了使对象能够进行序列化和反序列化,需要实现 <code>Serializable</code> 接口,并确保对象的所有引用类型字段也是可序列化的。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeeklyLog</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> {</span><br><span class="line"> <span class="keyword">private</span> Attachment attachment;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"> <span class="keyword">private</span> String date;</span><br><span class="line"> <span class="keyword">private</span> String content;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAttachment</span><span class="params">(Attachment attachment)</span> {</span><br><span class="line"> <span class="built_in">this</span>.attachment = attachment;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDate</span><span class="params">(String date)</span> {</span><br><span class="line"> <span class="built_in">this</span>.date = date;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setContent</span><span class="params">(String content)</span> {</span><br><span class="line"> <span class="built_in">this</span>.content = content;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> Attachment <span class="title function_">getAttachment</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.attachment);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.name);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getDate</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.date);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">getContent</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> (<span class="built_in">this</span>.content);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//使用序列化技术实现深克隆</span></span><br><span class="line"> <span class="keyword">public</span> WeeklyLog <span class="title function_">deepClone</span><span class="params">()</span> <span class="keyword">throws</span> IOException, ClassNotFoundException, OptionalDataException {</span><br><span class="line"> <span class="comment">//将对象写入流中</span></span><br><span class="line"> ByteArrayOutputStream bao=<span class="keyword">new</span> <span class="title class_">ByteArrayOutputStream</span>();</span><br><span class="line"> ObjectOutputStream oos=<span class="keyword">new</span> <span class="title class_">ObjectOutputStream</span>(bao);</span><br><span class="line"> oos.writeObject(<span class="built_in">this</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//将对象从流中取出</span></span><br><span class="line"> ByteArrayInputStream bis=<span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(bao.toByteArray());</span><br><span class="line"> ObjectInputStream ois=<span class="keyword">new</span> <span class="title class_">ObjectInputStream</span>(bis);</span><br><span class="line"> <span class="keyword">return</span> (WeeklyLog)ois.readObject();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h2><h3 id="介绍-7"><a href="#介绍-7" class="headerlink" title="介绍"></a>介绍</h3><p>一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。</p>
<h3 id="结构-7"><a href="#结构-7" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230530150040291.png" alt="image-20230530150040291"></p>
<h3 id="角色-7"><a href="#角色-7" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Singleton(单例)</li>
</ul>
<h3 id="实现-7"><a href="#实现-7" class="headerlink" title="实现"></a>实现</h3><h4 id="饿汉式"><a href="#饿汉式" class="headerlink" title="饿汉式"></a>饿汉式</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Singleton</span> {</span><br><span class="line"> <span class="comment">// 私有静态变量,用于保存单例实例</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">Singleton</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 私有构造函数,防止外部直接实例化对象</span></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">Singleton</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 初始化操作</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 公共静态方法,提供全局访问点获取单例实例</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="懒汉式"><a href="#懒汉式" class="headerlink" title="懒汉式"></a>懒汉式</h4><ul>
<li>基础版</li>
</ul>
<p>多线程环境下可能会出现问题。如果多个线程同时访问<code>getInstance()</code>方法,并且在<code>instance</code>还未被创建时,那么每个线程都会通过判断<code>instance</code>为<code>null</code>的条件,并创建一个新的实例。这样就会破坏单例的唯一性,导致多个实例被创建。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LazySingleton</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">LazySingleton</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">LazySingleton</span><span class="params">()</span> { }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> LazySingleton <span class="title function_">getInstance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (instance == <span class="literal">null</span>) {</span><br><span class="line"> instance = <span class="keyword">new</span> <span class="title class_">LazySingleton</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<ul>
<li>添加锁方法</li>
</ul>
<p>通过<code>synchronized</code>关键字修饰<code>getInstance()</code>方法,以确保在多线程环境下只创建一个实例。当第一个线程调用<code>getInstance()</code>方法时,如果实例尚未创建,它将创建一个新的实例</p>
<p><u>存在缺点</u>:</p>
<ol>
<li>每次调用<code>getInstance()</code>方法都会进入<code>synchronized</code>同步块,即使实例已经被创建。这会造成不必要的同步开销,影响性能。</li>
<li>在多线程环境下,当多个线程同时通过第一个判断条件<code>instance == null</code>时,它们会依次进入<code>synchronized</code>同步块,而只有一个线程能够创建实例,其他线程会被阻塞。这可能会引起线程竞争和性能问题。</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LazySingleton</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">LazySingleton</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">LazySingleton</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 私有构造函数,防止外部直接实例化对象</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 公共静态方法,提供全局访问点获取单例实例</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 单例实例</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">synchronized</span> <span class="keyword">public</span> <span class="keyword">static</span> LazySingleton <span class="title function_">getInstance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (instance == <span class="literal">null</span>) {</span><br><span class="line"> <span class="comment">// 如果实例为空,则创建新的实例</span></span><br><span class="line"> instance = <span class="keyword">new</span> <span class="title class_">LazySingleton</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ul>
<li>锁代码段</li>
</ul>
<p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230530151643226.png" alt="image-20230530151643226"></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LazySingleton</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="keyword">static</span> <span class="type">LazySingleton</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">LazySingleton</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 私有构造函数</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> LazySingleton <span class="title function_">getInstance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (instance == <span class="literal">null</span>) { <span class="comment">// 第一个判断,避免不必要的同步</span></span><br><span class="line"> <span class="keyword">synchronized</span> (LazySingleton.class) { <span class="comment">// synchronized关键字修饰的同步块</span></span><br><span class="line"> <span class="keyword">if</span> (instance == <span class="literal">null</span>) { <span class="comment">// 第二个判断,确保只有一个线程创建实例</span></span><br><span class="line"> instance = <span class="keyword">new</span> <span class="title class_">LazySingleton</span>();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="静态内部类"><a href="#静态内部类" class="headerlink" title="静态内部类"></a>静态内部类</h4><p>==相关介绍==:</p>
<p>在静态内部类中定义的静态方法可以直接被调用,不需要通过创建内部类的实例来访问。静态内部类与外部类之间是独立的,因此可以直接访问静态内部类中的静态成员,包括静态方法。</p>
<p>在上述示例中,静态内部类<code>HolderClass</code>中的<code>instance</code>变量是私有静态的,而<code>getInstance()</code>方法是公共静态的。这意味着可以通过<code>Singleton.HolderClass.instance</code>直接访问<code>instance</code>变量,也可以通过<code>Singleton.getInstance()</code>调用<code>getInstance()</code>方法来获取单例实例。这种方式提供了更简洁的访问方式,无需显式创建内部类实例。</p>
<p>需要注意的是,静态内部类中不能直接访问外部类的非静态成员,因为静态内部类在没有外部类实例的情况下也可以被访问。如果需要访问外部类的非静态成员,可以通过创建外部类的实例来实现。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// Initialization on Demand Holder</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Singleton</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="title function_">Singleton</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// 私有构造函数,防止外部直接实例化对象</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 静态内部类</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">HolderClass</span> {</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> <span class="type">Singleton</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Singleton</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 公共静态方法,提供全局访问点获取单例实例</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 单例实例</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title function_">getInstance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> HolderClass.instance;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 对应调用方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Main</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">Singleton</span> <span class="variable">singleton</span> <span class="operator">=</span> Singleton.getInstance();</span><br><span class="line"> <span class="comment">// 使用单例对象</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="桥接模式"><a href="#桥接模式" class="headerlink" title="桥接模式"></a>桥接模式</h2><h3 id="介绍-8"><a href="#介绍-8" class="headerlink" title="介绍"></a>介绍</h3><p>桥接模式是一种结构型设计模式,它旨在将抽象部分与其实现部分分离,使它们可以独立地变化。它通过创建一个桥接接口,将抽象和实现解耦,使它们可以独立地进行扩展。</p>
<p>在桥接模式中,存在两个维度的抽象和实现,通过桥接接口将它们连接起来。其中,抽象部分定义了高层的抽象方法和属性,而实现部分定义了具体实现的方法和属性。通过桥接接口,抽象部分和实现部分可以独立地进行扩展和变化,而彼此之间的关系通过桥接接口来实现。</p>
<h3 id="结构-8"><a href="#结构-8" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230530152030299.png" alt="image-20230530152030299"></p>
<h3 id="角色-8"><a href="#角色-8" class="headerlink" title="角色"></a>角色</h3><ul>
<li>Abstraction(抽象类)</li>
<li>Refined Abstraction(扩充抽象类)</li>
<li>Implementor(实现类接口)</li>
<li>Concrete Implementor(具体实现类)</li>
</ul>
<h3 id="实现-8"><a href="#实现-8" class="headerlink" title="实现"></a>实现</h3><p><strong>理解</strong>:通过桥接模式,图像实现类(如 <code>LinuxImp</code>)和操作系统实现类(如 <code>Linux</code>)被解耦,它们可以独立地变化和扩展。图像实现类负责将图像数据转换成特定格式(如像素矩阵),而操作系统实现类负责将像素矩阵在特定操作系统中进行显示。这样,通过注入不同的图像实现类和操作系统实现类,可以实现不同图像格式在不同操作系统下的显示,而不需要修改现有的类结构。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象图像类,充当抽象类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Image</span> {</span><br><span class="line"> <span class="keyword">protected</span> ImageImp imp;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//注入实现类接口对象</span></span><br><span class="line"> <span class="comment">//桥接的关键位置</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setImageImp</span><span class="params">(ImageImp imp)</span> {</span><br><span class="line"> <span class="built_in">this</span>.imp = imp;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//解析文件</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">parseFile</span><span class="params">(String fileName)</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//具体图像类</span></span><br><span class="line"><span class="comment">//BMP格式图像类,充当扩充抽象类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BMPImage</span> <span class="keyword">extends</span> <span class="title class_">Image</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">parseFile</span><span class="params">(String fileName)</span> {</span><br><span class="line"> <span class="comment">//模拟解析BMP文件并获得一个像素矩阵对象m;</span></span><br><span class="line"> <span class="type">Matrix</span> <span class="variable">m</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Matrix</span>();</span><br><span class="line"> imp.doPaint(m);</span><br><span class="line"> System.out.println(fileName + <span class="string">",格式为BMP。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//GIF格式图像类,充当扩充抽象类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GIFImage</span> <span class="keyword">extends</span> <span class="title class_">Image</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">parseFile</span><span class="params">(String fileName)</span> {</span><br><span class="line"> <span class="comment">//模拟解析GIF文件并获得一个像素矩阵对象m;</span></span><br><span class="line"> <span class="type">Matrix</span> <span class="variable">m</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Matrix</span>();</span><br><span class="line"> imp.doPaint(m);</span><br><span class="line"> System.out.println(fileName + <span class="string">",格式为GIF。"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象操作系统实现类,充当实现类接口</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ImageImp</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doPaint</span><span class="params">(Matrix m)</span>; <span class="comment">//显示像素矩阵m</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//Linux操作系统实现类,充当具体实现类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LinuxImp</span> <span class="keyword">implements</span> <span class="title class_">ImageImp</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doPaint</span><span class="params">(Matrix m)</span> {</span><br><span class="line"> <span class="comment">//调用Linux系统的绘制函数绘制像素矩阵</span></span><br><span class="line"> System.out.print(<span class="string">"在Linux操作系统中显示图像:"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//像素矩阵类,辅助类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Matrix</span> {</span><br><span class="line"> <span class="comment">//代码省略</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="状态模式"><a href="#状态模式" class="headerlink" title="状态模式"></a>状态模式</h2><h3 id="介绍-9"><a href="#介绍-9" class="headerlink" title="介绍"></a>介绍</h3><p>它允许对象在内部状态改变时改变其行为。该模式将对象的行为封装在不同的状态对象中,使得对象在不同状态下具有不同的行为,同时将状态的切换和行为的执行解耦。</p>
<h3 id="结构-9"><a href="#结构-9" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230531170222824.png" alt="image-20230531170222824"></p>
<h3 id="角色-9"><a href="#角色-9" class="headerlink" title="角色"></a>角色</h3><ul>
<li><p>Context(环境类)</p>
</li>
<li><p>State(抽象状态类)</p>
</li>
<li><p>Concrete State(具体状态类)</p>
</li>
</ul>
<h3 id="实现-9"><a href="#实现-9" class="headerlink" title="实现"></a>实现</h3><p>具体的状态转换逻辑位于具体状态类中,每个状态类负责自己的状态转换和相应的操作</p>
<p>還有另外幾種狀態類的轉換方式 只提供對對應轉換方式代碼</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象開關對象</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">SwitchState</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">on</span><span class="params">(Switch s)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">off</span><span class="params">(Switch s)</span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具體開關對象</span></span><br><span class="line"><span class="comment">// 方法中會傳入一個對象 并修改該對象的currentstate</span></span><br><span class="line"><span class="comment">// 具體代碼可見switch</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//打开状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OnState</span> <span class="keyword">extends</span> <span class="title class_">SwitchState</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">on</span><span class="params">(Switch s)</span> {</span><br><span class="line"> System.out.println(<span class="string">"已经打开!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">off</span><span class="params">(Switch s)</span> {</span><br><span class="line"> System.out.println(<span class="string">"关闭!"</span>);</span><br><span class="line"> s.setState(Switch.getState(<span class="string">"off"</span>));</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//关闭状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OffState</span> <span class="keyword">extends</span> <span class="title class_">SwitchState</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">on</span><span class="params">(Switch s)</span> {</span><br><span class="line"> System.out.println(<span class="string">"打开!"</span>);</span><br><span class="line"> s.setState(Switch.getState(<span class="string">"on"</span>));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">off</span><span class="params">(Switch s)</span> {</span><br><span class="line"> System.out.println(<span class="string">"已经关闭!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Switch</span> {</span><br><span class="line"> <span class="comment">//定义三个静态的状态对象 所有的开关对象共享状态</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> SwitchState currentState,onState,offState;</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 构造函数 默认状态为开启</span></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Switch</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> onState = <span class="keyword">new</span> <span class="title class_">OnState</span>();</span><br><span class="line"> offState = <span class="keyword">new</span> <span class="title class_">OffState</span>();</span><br><span class="line"> currentState = onState;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 該方法會被狀態方法進行調用</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setState</span><span class="params">(SwitchState state)</span> {</span><br><span class="line"> currentState = state;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> SwitchState <span class="title function_">getState</span><span class="params">(String type)</span> {</span><br><span class="line"> <span class="keyword">if</span> (type.equalsIgnoreCase(<span class="string">"on"</span>)) {</span><br><span class="line"> <span class="keyword">return</span> onState;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> offState;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">//下面兩個方法會將當前對象傳入 若狀態改變則會對對cuurent進行修改</span></span><br><span class="line"> <span class="comment">//打开开关</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">on</span><span class="params">()</span> {</span><br><span class="line"> System.out.print(name);</span><br><span class="line"> currentState.on(<span class="built_in">this</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//关闭开关</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">off</span><span class="params">()</span> {</span><br><span class="line"> System.out.print(name);</span><br><span class="line"> currentState.off(<span class="built_in">this</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="其餘轉換方式實現"><a href="#其餘轉換方式實現" class="headerlink" title="其餘轉換方式實現"></a>其餘轉換方式實現</h3><ul>
<li>放大鏡</li>
</ul>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//在環境類中進行轉換</span></span><br><span class="line"><span class="comment">//屏幕类:环境类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Screen</span> {</span><br><span class="line"> <span class="comment">//枚举所有的状态,currentState表示当前状态</span></span><br><span class="line"> <span class="keyword">private</span> ScreenState currentState, normalState, largerState, largestState;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Screen</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">this</span>.normalState = <span class="keyword">new</span> <span class="title class_">NormalState</span>(); <span class="comment">//创建正常状态对象</span></span><br><span class="line"> <span class="built_in">this</span>.largerState = <span class="keyword">new</span> <span class="title class_">LargerState</span>(); <span class="comment">//创建二倍放大状态对象</span></span><br><span class="line"> <span class="built_in">this</span>.largestState = <span class="keyword">new</span> <span class="title class_">LargestState</span>(); <span class="comment">//创建四倍放大状态对象</span></span><br><span class="line"> <span class="built_in">this</span>.currentState = normalState; <span class="comment">//设置初始状态</span></span><br><span class="line"> <span class="built_in">this</span>.currentState.display();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setState</span><span class="params">(ScreenState state)</span> {</span><br><span class="line"> <span class="built_in">this</span>.currentState = state;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//单击事件处理方法,封转了对状态类中业务方法的调用和状态的转换</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onClick</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">this</span>.currentState == normalState) {</span><br><span class="line"> <span class="built_in">this</span>.setState(largerState);</span><br><span class="line"> <span class="built_in">this</span>.currentState.display();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">this</span>.currentState == largerState) {</span><br><span class="line"> <span class="built_in">this</span>.setState(largestState);</span><br><span class="line"> <span class="built_in">this</span>.currentState.display();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">this</span>.currentState == largestState) {</span><br><span class="line"> <span class="built_in">this</span>.setState(normalState);</span><br><span class="line"> <span class="built_in">this</span>.currentState.display();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<ul>
<li>銀行賬戶</li>
</ul>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//银行账户:环境类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Account</span> {</span><br><span class="line"> <span class="keyword">private</span> AccountState state; <span class="comment">//维持一个对抽象状态对象的引用</span></span><br><span class="line"> <span class="keyword">private</span> String owner; <span class="comment">//开户名</span></span><br><span class="line"> <span class="keyword">private</span> <span class="type">double</span> <span class="variable">balance</span> <span class="operator">=</span> <span class="number">0</span>; <span class="comment">//账户余额</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Account</span><span class="params">(String owner,<span class="type">double</span> init)</span> {</span><br><span class="line"> <span class="built_in">this</span>.owner = owner;</span><br><span class="line"> <span class="built_in">this</span>.balance = balance;</span><br><span class="line"> <span class="built_in">this</span>.state = <span class="keyword">new</span> <span class="title class_">NormalState</span>(<span class="built_in">this</span>); <span class="comment">//设置初始状态</span></span><br><span class="line"> System.out.println(<span class="built_in">this</span>.owner + <span class="string">"开户,初始金额为"</span> + init);</span><br><span class="line"> System.out.println(<span class="string">"---------------------------------------------"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">getBalance</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">this</span>.balance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setBalance</span><span class="params">(<span class="type">double</span> balance)</span> {</span><br><span class="line"> <span class="built_in">this</span>.balance = balance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setState</span><span class="params">(AccountState state)</span> {</span><br><span class="line"> <span class="built_in">this</span>.state = state;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deposit</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> System.out.println(<span class="built_in">this</span>.owner + <span class="string">"存款"</span> + amount);</span><br><span class="line"> state.deposit(amount); <span class="comment">//调用状态对象的deposit()方法</span></span><br><span class="line"> System.out.println(<span class="string">"现在余额为"</span>+ <span class="built_in">this</span>.balance);</span><br><span class="line"> System.out.println(<span class="string">"现在帐户状态为"</span>+ <span class="built_in">this</span>.state.getClass().getName());</span><br><span class="line"> System.out.println(<span class="string">"---------------------------------------------"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> System.out.println(<span class="built_in">this</span>.owner + <span class="string">"取款"</span> + amount);</span><br><span class="line"> state.withdraw(amount); <span class="comment">//调用状态对象的withdraw()方法</span></span><br><span class="line"> System.out.println(<span class="string">"现在余额为"</span>+ <span class="built_in">this</span>.balance);</span><br><span class="line"> System.out.println(<span class="string">"现在帐户状态为"</span>+ <span class="built_in">this</span>. state.getClass().getName());</span><br><span class="line"> System.out.println(<span class="string">"---------------------------------------------"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">computeInterest</span><span class="params">()</span></span><br><span class="line"> {</span><br><span class="line"> state.computeInterest(); <span class="comment">//调用状态对象的computeInterest()方法</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//抽象状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AccountState</span> {</span><br><span class="line"> <span class="keyword">protected</span> Account acc;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">deposit</span><span class="params">(<span class="type">double</span> amount)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(<span class="type">double</span> amount)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">computeInterest</span><span class="params">()</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">stateCheck</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//正常状态:具体状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NormalState</span> <span class="keyword">extends</span> <span class="title class_">AccountState</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">NormalState</span><span class="params">(Account acc)</span> {</span><br><span class="line"> <span class="built_in">this</span>.acc = acc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">NormalState</span><span class="params">(AccountState state)</span> {</span><br><span class="line"> <span class="built_in">this</span>.acc = state.acc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deposit</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> acc.setBalance(acc.getBalance() + amount);</span><br><span class="line"> stateCheck();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> acc.setBalance(acc.getBalance() - amount);</span><br><span class="line"> stateCheck();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">computeInterest</span><span class="params">()</span></span><br><span class="line"> {</span><br><span class="line"> System.out.println(<span class="string">"正常状态,无须支付利息!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//状态转换</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stateCheck</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (acc.getBalance() > -<span class="number">2000</span> && acc.getBalance() <= <span class="number">0</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">OverdraftState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (acc.getBalance() == -<span class="number">2000</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">RestrictedState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (acc.getBalance() < -<span class="number">2000</span>) {</span><br><span class="line"> System.out.println(<span class="string">"操作受限!"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//透支状态:具体状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OverdraftState</span> <span class="keyword">extends</span> <span class="title class_">AccountState</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">OverdraftState</span><span class="params">(AccountState state)</span> {</span><br><span class="line"> <span class="built_in">this</span>.acc = state.acc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deposit</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> acc.setBalance(acc.getBalance() + amount);</span><br><span class="line"> stateCheck();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> acc.setBalance(acc.getBalance() - amount);</span><br><span class="line"> stateCheck();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">computeInterest</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"计算利息!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//状态转换</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stateCheck</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span> (acc.getBalance() > <span class="number">0</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">NormalState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (acc.getBalance() == -<span class="number">2000</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">RestrictedState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (acc.getBalance() < -<span class="number">2000</span>) {</span><br><span class="line"> System.out.println(<span class="string">"操作受限!"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//受限状态:具体状态类</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RestrictedState</span> <span class="keyword">extends</span> <span class="title class_">AccountState</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">RestrictedState</span><span class="params">(AccountState state)</span> {</span><br><span class="line"> <span class="built_in">this</span>.acc = state.acc;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deposit</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> acc.setBalance(acc.getBalance() + amount);</span><br><span class="line"> stateCheck();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(<span class="type">double</span> amount)</span> {</span><br><span class="line"> System.out.println(<span class="string">"帐号受限,取款失败"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">computeInterest</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"计算利息!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//状态转换</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">stateCheck</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">if</span>(acc.getBalance() > <span class="number">0</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">NormalState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(acc.getBalance() > -<span class="number">2000</span>) {</span><br><span class="line"> acc.setState(<span class="keyword">new</span> <span class="title class_">OverdraftState</span>(<span class="built_in">this</span>));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String args[])</span> {</span><br><span class="line"> <span class="type">Account</span> <span class="variable">acc</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Account</span>(<span class="string">"段誉"</span>,<span class="number">0.0</span>);</span><br><span class="line"> acc.deposit(<span class="number">1000</span>);</span><br><span class="line"> acc.withdraw(<span class="number">2000</span>);</span><br><span class="line"> acc.deposit(<span class="number">3000</span>);</span><br><span class="line"> acc.withdraw(<span class="number">4000</span>);</span><br><span class="line"> acc.withdraw(<span class="number">1000</span>);</span><br><span class="line"> acc.computeInterest();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="命令模式"><a href="#命令模式" class="headerlink" title="命令模式"></a>命令模式</h2><h3 id="介绍-10"><a href="#介绍-10" class="headerlink" title="介绍"></a>介绍</h3><p>命令模式(Command Pattern)用于将请求(命令)封装成一个对象,使得可以将不同的请求参数化并且支持请求的排队、记录日志、撤销等操作</p>
<h3 id="结构-10"><a href="#结构-10" class="headerlink" title="结构"></a>结构</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230531111839798.png" alt="image-20230531111839798"></p>
<h3 id="角色-10"><a href="#角色-10" class="headerlink" title="角色"></a>角色</h3><ul>
<li>命令接口(Command)</li>
<li>具体命令(Concrete Command)</li>
<li>命令接收者(Receiver)</li>
<li>命令发起者(Invoker)</li>
</ul>
<h3 id="实现-10"><a href="#实现-10" class="headerlink" title="实现"></a>实现</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 抽象命令</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">Command</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">execute</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 具体命令</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 帮助</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelpCommand</span> <span class="keyword">extends</span> <span class="title class_">Command</span> {</span><br><span class="line"> <span class="keyword">private</span> DisplayHelpClass hcObj; <span class="comment">//维持对请求接收者的引用</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">HelpCommand</span><span class="params">()</span> {</span><br><span class="line"> hcObj = <span class="keyword">new</span> <span class="title class_">DisplayHelpClass</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//命令执行方法,将调用请求接收者的业务方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">execute</span><span class="params">()</span> {</span><br><span class="line"> hcObj.display();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 退出</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExitCommand</span> <span class="keyword">extends</span> <span class="title class_">Command</span> {</span><br><span class="line"> <span class="keyword">private</span> SystemExitClass seObj; <span class="comment">//维持对请求接收者的引用</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ExitCommand</span><span class="params">()</span> {</span><br><span class="line"> seObj = <span class="keyword">new</span> <span class="title class_">SystemExitClass</span>();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//命令执行方法,将调用请求接收者的业务方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">execute</span><span class="params">()</span> {</span><br><span class="line"> seObj.exit();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 接收者</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DisplayHelpClass</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">display</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"显示帮助文档!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SystemExitClass</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">exit</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"退出系统!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 调用者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FunctionButton</span> {</span><br><span class="line"> <span class="keyword">private</span> Command command; <span class="comment">//维持一个抽象命令对象的引用</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//为功能键注入命令</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setCommand</span><span class="params">(Command command)</span> {</span><br><span class="line"> <span class="built_in">this</span>.command = command;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//发送请求的方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">click</span><span class="params">()</span> {</span><br><span class="line"> System.out.print(<span class="string">"单击功能键: "</span>);</span><br><span class="line"> command.execute();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 客户端</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String args[])</span> {</span><br><span class="line"></span><br><span class="line"> <span class="type">FunctionButton</span> <span class="variable">fb</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">FunctionButton</span>();</span><br><span class="line"></span><br><span class="line"> Command command; <span class="comment">//定义命令对象</span></span><br><span class="line"> command = (Command)XMLUtil.getBean(); <span class="comment">//读取配置文件,反射生成对象</span></span><br><span class="line"></span><br><span class="line"> fb.setCommand(command); <span class="comment">//将命令对象注入功能键</span></span><br><span class="line"> fb.click(); <span class="comment">//调用功能键的业务方法</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="組合模式"><a href="#組合模式" class="headerlink" title="組合模式"></a>組合模式</h2><h3 id="介紹"><a href="#介紹" class="headerlink" title="介紹"></a>介紹</h3><p>组合模式是一种结构型设计模式,用于将对象组合成树形结构以表示”部分-整体”的层次关系,使得用户对单个对象和组合对象的使用具有一致性。</p>
<h3 id="結構"><a href="#結構" class="headerlink" title="結構"></a>結構</h3><p><img src="https://oooooo.oss-cn-fuzhou.aliyuncs.com/img/image-20230531172221176.png" alt="image-20230531172221176"></p>
<h3 id="角色-11"><a href="#角色-11" class="headerlink" title="角色"></a>角色</h3><ul>
<li>组件(Component):是组合中的抽象基类,定义了组合对象和叶子对象的共有操作接口。它可以是抽象类或接口,声明了一些用于管理子对象的方法,例如添加、删除、获取子对象等。</li>
<li>叶子(Leaf):是组合中的叶子节点,表示组合对象中的基本元素,它没有子对象。</li>
<li>容器(Composite):是组合中的容器节点,表示可以包含子对象的复杂对象。容器对象中通常会持有一个或多个子对象,并实现组合对象的共有操作接口。容器对象的操作会递归地调用子对象的操作,以实现对整个树形结构的操作。</li>
<li>客户端(Client):通过组合对象的操作接口来操作组合对象和叶子对象。</li>
</ul>
<h3 id="實現"><a href="#實現" class="headerlink" title="實現"></a>實現</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//組件</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbstractFile</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(AbstractFile file)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(AbstractFile file)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> AbstractFile <span class="title function_">getChild</span><span class="params">(<span class="type">int</span> i)</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">void</span> <span class="title function_">killVirus</span><span class="params">()</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//容器</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Folder</span> <span class="keyword">extends</span> <span class="title class_">AbstractFile</span> {</span><br><span class="line"> <span class="comment">//定义集合fileList,用于存储AbstractFile类型的成员</span></span><br><span class="line"> <span class="keyword">private</span> ArrayList<AbstractFile> fileList=<span class="keyword">new</span> <span class="title class_">ArrayList</span><AbstractFile>();</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Folder</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> fileList.add(file);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> fileList.remove(file);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> AbstractFile <span class="title function_">getChild</span><span class="params">(<span class="type">int</span> i)</span> {</span><br><span class="line"> <span class="keyword">return</span> (AbstractFile)fileList.get(i);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">killVirus</span><span class="params">()</span> {</span><br><span class="line"> System.out.println(<span class="string">"****对文件夹'"</span> + name + <span class="string">"'进行杀毒"</span>); <span class="comment">//模拟杀毒</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">//递归调用成员构件的killVirus()方法</span></span><br><span class="line"> <span class="keyword">for</span>(Object obj : fileList) {</span><br><span class="line"> ((AbstractFile)obj).killVirus();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//葉子</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//ImageFile</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ImageFile</span> <span class="keyword">extends</span> <span class="title class_">AbstractFile</span> {</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">ImageFile</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> AbstractFile <span class="title function_">getChild</span><span class="params">(<span class="type">int</span> i)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">killVirus</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//模拟杀毒</span></span><br><span class="line"> System.out.println(<span class="string">"----对图像文件'"</span> + name + <span class="string">"'进行杀毒"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//TextFile</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TextFile</span> <span class="keyword">extends</span> <span class="title class_">AbstractFile</span> {</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">TextFile</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> AbstractFile <span class="title function_">getChild</span><span class="params">(<span class="type">int</span> i)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">killVirus</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//模拟杀毒</span></span><br><span class="line"> System.out.println(<span class="string">"----对文本文件'"</span> + name + <span class="string">"'进行杀毒"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//VideoFile</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VideoFile</span> <span class="keyword">extends</span> <span class="title class_">AbstractFile</span> {</span><br><span class="line"> <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">VideoFile</span><span class="params">(String name)</span> {</span><br><span class="line"> <span class="built_in">this</span>.name = name;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">remove</span><span class="params">(AbstractFile file)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> AbstractFile <span class="title function_">getChild</span><span class="params">(<span class="type">int</span> i)</span> {</span><br><span class="line"> System.out.println(<span class="string">"对不起,不支持该方法!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">killVirus</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">//模拟杀毒</span></span><br><span class="line"> System.out.println(<span class="string">"----对视频文件'"</span> + name + <span class="string">"'进行杀毒"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//客戶端</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String args[])</span> {</span><br><span class="line"> <span class="comment">//针对抽象构件编程</span></span><br><span class="line"> AbstractFile file1,file2,file3,file4,file5,folder1,folder2,folder3,folder4;</span><br><span class="line"></span><br><span class="line"> folder1 = <span class="keyword">new</span> <span class="title class_">Folder</span>(<span class="string">"Sunny的资料"</span>);</span><br><span class="line"> folder2 = <span class="keyword">new</span> <span class="title class_">Folder</span>(<span class="string">"图像文件"</span>);</span><br><span class="line"> folder3 = <span class="keyword">new</span> <span class="title class_">Folder</span>(<span class="string">"文本文件"</span>);</span><br><span class="line"> folder4 = <span class="keyword">new</span> <span class="title class_">Folder</span>(<span class="string">"视频文件"</span>);</span><br><span class="line"></span><br><span class="line"> file1 = <span class="keyword">new</span> <span class="title class_">ImageFile</span>(<span class="string">"小龙女.jpg"</span>);</span><br><span class="line"> file2 = <span class="keyword">new</span> <span class="title class_">ImageFile</span>(<span class="string">"张无忌.gif"</span>);</span><br><span class="line"> file3 = <span class="keyword">new</span> <span class="title class_">TextFile</span>(<span class="string">"九阴真经.txt"</span>);</span><br><span class="line"> file4 = <span class="keyword">new</span> <span class="title class_">TextFile</span>(<span class="string">"葵花宝典.doc"</span>);</span><br><span class="line"> file5 = <span class="keyword">new</span> <span class="title class_">VideoFile</span>(<span class="string">"笑傲江湖.rmvb"</span>);</span><br><span class="line"></span><br><span class="line"> folder2.add(file1);</span><br><span class="line"> folder2.add(file2);</span><br><span class="line"> folder3.add(file3);</span><br><span class="line"> folder3.add(file4);</span><br><span class="line"> folder4.add(file5);</span><br><span class="line"></span><br><span class="line"> folder1.add(folder2);</span><br><span class="line"> folder1.add(folder3);</span><br><span class="line"> folder1.add(folder4);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//从“Sunny的资料”结点开始进行杀毒操作</span></span><br><span class="line"> folder1.killVirus();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="模式(模板)"><a href="#模式(模板)" class="headerlink" title="模式(模板)"></a>模式(模板)</h2><h3 id="介紹-1"><a href="#介紹-1" class="headerlink" title="介紹"></a>介紹</h3><h3 id="結構-1"><a href="#結構-1" class="headerlink" title="結構"></a>結構</h3><h3 id="角色-12"><a href="#角色-12" class="headerlink" title="角色"></a>角色</h3><h3 id="實現-1"><a href="#實現-1" class="headerlink" title="實現"></a>實現</h3>]]></content>
<categories>
<category>软件设计与架构</category>
</categories>
<tags>
<tag>java</tag>
<tag>designPattern</tag>
</tags>
</entry>
</search>