-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.print.html
251 lines (251 loc) · 50.8 KB
/
index.print.html
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
<!doctype html><html lang=zh-cn dir=ltr><head><meta charset=utf-8><meta name=viewport content="height=device-height,width=device-width,initial-scale=1,minimum-scale=1"><meta name=generator content="Hugo 0.110.0"><meta name=generator content="Relearn 5.11.1+tip"><meta name=description content="Documentation for Hugo Relearn Theme"><meta name=author content="waouooo"><title>个人博客</title><link href=https://zhou-yi-git.github.io/index.html rel=canonical type=text/html title=个人博客><link href=./index.xml rel=alternate type=application/rss+xml title=个人博客><link href=./css/fontawesome-all.min.css?1676435289 rel=stylesheet media=print onload='this.media="all",this.onload=null'><noscript><link href=./css/fontawesome-all.min.css?1676435289 rel=stylesheet></noscript><link href=./css/auto-complete.css?1676435289 rel=stylesheet media=print onload='this.media="all",this.onload=null'><noscript><link href=./css/auto-complete.css?1676435289 rel=stylesheet></noscript><link href=./css/perfect-scrollbar.min.css?1676435289 rel=stylesheet><link href=./css/nucleus.css?1676435289 rel=stylesheet><link href=./css/fonts.css?1676435289 rel=stylesheet media=print onload='this.media="all",this.onload=null'><noscript><link href=./css/fonts.css?1676435289 rel=stylesheet></noscript><link href=./css/theme.css?1676435289 rel=stylesheet><link href=./css/theme-relearn-light.css?1676435289 rel=stylesheet id=variant-style><link href=./css/ie.css?1676435289 rel=stylesheet><link href=./css/variant.css?1676435289 rel=stylesheet><link href=./css/print.css?1676435289 rel=stylesheet media=print><link href=./css/format-print.css?1676435289 rel=stylesheet><script src=./js/url.js?1676435289></script>
<script src=./js/variant.js?1676435289></script>
<script>window.index_js_url="./index.search.js";var root_url="./",baseUriFull,baseUri=root_url.replace(/\/$/,"");window.T_Copy_to_clipboard="复制到剪贴板",window.T_Copied_to_clipboard="复制到剪贴板!",window.T_Copy_link_to_clipboard="将链接复制到剪贴板",window.T_Link_copied_to_clipboard="链接复制到剪贴板!",window.T_No_results_found="找不到\u0022{0}\u0022的结果",window.T_N_results_found="为\u0022{0}\u0022找到 {1} 个结果",baseUriFull="https://zhou-yi-git.github.io/",window.variants&&variants.init(["relearn-light","relearn-dark","learn","neon","blue","green","red"])</script></head><body class="mobile-support print disableInlineCopyToClipboard" data-url=./index.html><div id=body class=default-animation><div id=sidebar-overlay></div><div id=toc-overlay></div><nav id=topbar class=highlightable dir=ltr><div><div id=breadcrumbs><span id=sidebar-toggle-span><a href=# id=sidebar-toggle class=topbar-link title='导航 (CTRL+ALT+n)'><i class="fas fa-bars fa-fw"></i></a></span><ol class=links itemscope itemtype=http://schema.org/BreadcrumbList><li itemscope itemtype=https://schema.org/ListItem itemprop=itemListElement><span itemprop=name>个人博客</span><meta itemprop=position content="1"></li></ol></div></div></nav><main id=body-inner class="highlightable home" tabindex=-1><div class=flex-block-wrapper><div id=head-tags></div><article class="home deprecated"><h1 id=个人博客>个人博客</h1><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><section><h1 class=a11y-only>个人博客 的子部分</h1><article class=chapter><div class=article-subheading>第4章</div><h1 id=设计模式>设计模式</h1><p>23种设计模式.</p><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><section><h1 class=a11y-only>设计模式 的子部分</h1><article class=default><h1 id=六大设计原则>六大设计原则</h1><h1 id=六大设计原则>六大设计原则</h1><p>[toc]</p><h3 id=单一职责原则-single-responsibility-principle-srp>单一职责原则 (Single Responsibility Principle: SRP)</h3><h4 id=定义应该有且仅有一个原因引起类的变更-适用范围接口方法类>定义:应该有,且仅有一个原因引起类的变更 (适用范围,接口,方法,类)</h4><blockquote><p>“There should never be more than one reason for a class to change.”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p><p>定义:应该有,且仅有一个原因引起类的变更 (适用范围,接口,方法,类)</p></blockquote><h4 id=建议-对于单一职责原则我的建议是接口一定要做到单一职责类的设计尽量做到只有一个原因引起变化一个方法尽可能做一件事情>建议: <code>对于单一职责原则,我的建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化,一个方法尽可能做一件事情</code></h4><h4 id=单一职责的好处>单一职责的好处:</h4><ul><li><p>类的复杂性降低实现什么职责都有清晰明确的定义</p></li><li><p>可读性提高 (因为降低了类的复杂性)</p></li><li><p>可维护性提高(因为可读性提高了)</p></li><li><p>变更引起的风险降低:</p><p>接口的单一职责做的好,一个接口的修改只对相应的实现类有影响,对系统的拓展性与可维护性都有很大的帮助</p></li></ul><h3 id=里氏替换原则-liskov-substitution-principle-lsp>里氏替换原则 (Liskov Substitution Principle: LSP)</h3><h4 id=定义所有引用基类的地方必须能透明地使用其子类的对象>定义:所有引用基类的地方必须能透明地使用其子类的对象</h4><blockquote><p>定义一:</p><p>“If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。)”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p><p>定义二:</p><p>“Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象。)</p><p>第二使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p></blockquote><h4 id=里氏替换原则为良好的继承定义了规范>里氏替换原则为良好的继承定义了规范</h4><ul><li><p>子类必须完全实现父类的方法</p><ol><li><p>“在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则”</p></li><li><p>“如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承”</p></li></ol></li><li><p>子类可以有自己的个性</p></li><li><p>覆盖或实现父类的方法时输入参数可以被放大: 子类方法的前置条件必须与超类中被复写的方法的前置条件相同或更宽松</p><p>如果Father类的输入参数类型宽于子类的输入参数类型,会出现父类存在的地方,子类就未必可以存在,因为一旦把子类作为参数传入,调用者就很可能进入子类的方法范畴。</p><div class=highlight><pre tabindex=0 class=chroma><code class=language-java data-lang=java><span class=line><span class=cl><span class=c1>// 父类
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=kd>public</span> <span class=kd>class</span> <span class=nc>Father</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=n>Collection</span> <span class=nf>doSomething</span><span class=o>(</span><span class=n>HashMap</span> <span class=n>map</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=n>System</span><span class=o>.</span><span class=na>out</span><span class=o>.</span><span class=na>println</span><span class=o>(</span><span class=s>"父类被执行..."</span><span class=o>);</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>map</span><span class=o>.</span><span class=na>values</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 子类的输入参数是Map类型,也就是说子类的输入参数类型的范围扩大了
</span></span></span><span class=line><span class=cl><span class=cm> * 子类代替父类传递到调用者中,子类的方法永远都不会被执行
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nc>Son</span> <span class=kd>extends</span> <span class=n>Father</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=c1>//放大输入参数类型, 子类的方法永远不会执行
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>public</span> <span class=n>Collection</span> <span class=nf>doSomething</span><span class=o>(</span><span class=n>Map</span> <span class=n>map</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=n>System</span><span class=o>.</span><span class=na>out</span><span class=o>.</span><span class=na>println</span><span class=o>(</span><span class=s>"子类被执行..."</span><span class=o>);</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>map</span><span class=o>.</span><span class=na>values</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1>// 场景类
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=kd>public</span> <span class=kd>class</span> <span class=nc>Client</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kt>void</span> <span class=nf>invoker</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=c1>//父类存在的地方,子类就应该能够存在
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>Father</span> <span class=n>f</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Father</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=c1>//Son f = new Son();
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>HashMap</span> <span class=n>map</span> <span class=o>=</span> <span class=k>new</span> <span class=n>HashMap</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=n>f</span><span class=o>.</span><span class=na>doSomething</span><span class=o>(</span><span class=n>map</span><span class=o>);</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kt>void</span> <span class=nf>main</span><span class=o>(</span><span class=n>String</span><span class=o>[]</span> <span class=n>args</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=n>invoker</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span></code></pre></div><p>Note:<code>宽于基类,则子类的复写方法实际为方法重载,若如参为父类方法的类型,则子类方法不会被调用到,因其直接调用了其父类的方法</code></p><blockquote><p>“采用里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p></blockquote></li><li><p>复写或实现父类的方法时输出结果可以被缩小</p><p>父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一个类型,要么S是T的子类</p></li></ul><h4 id=最佳实践>最佳实践:</h4><blockquote><p>“在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了,把子类当做父类使用,子类的“个性”被抹杀——委屈了点;把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标准。”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p></blockquote><h3 id=依赖倒置原则-dependence-inversion-principle-dip>依赖倒置原则 (Dependence Inversion Principle: DIP)</h3><h4 id=定义>定义</h4><ol><li>高层模块不应该依赖底层模块,两者都应该依赖其抽象;</li><li>抽象不应该依赖细节;</li><li>细节应该依赖抽象;</li></ol><blockquote><p>“High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p><p>“依赖倒置原则在Java语言中的表现就是:</p><p>● 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;</p><p>● 接口或抽象类不依赖于实现类;</p><p>● 实现类依赖接口或抽象类。”</p><p>摘录来自: . “设计模式之禅(第2版)(华章原创精品)。” Apple Books.</p></blockquote><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><article class=default><h1 id=单例模式>单例模式</h1><h1 id=单例模式>单例模式</h1><h3 id=定义>定义:</h3><p>“确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例”</p><h3 id=通用代码>通用代码:</h3><div class=highlight><pre tabindex=0 class=chroma><code class=language-java data-lang=java><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nc>Singleton</span> <span class=o>{</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 定义的时候初始化对象/在static体重定义/在get方法中定义(此时的get方法加synchronized 修饰)
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kd>final</span> <span class=n>Singleton</span> <span class=n>singleton</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 私有化构造类,限制产生多个对象
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 获取实例对象
</span></span></span><span class=line><span class=cl><span class=cm> *
</span></span></span><span class=line><span class=cl><span class=cm> * @return
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getSingleton</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>singleton</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 类中其他方法,尽量是static
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kt>void</span> <span class=nf>doSomething</span><span class=o>(){</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span></code></pre></div><h3 id=优点>优点</h3><ul><li>减少内存开销,避免频繁创建销毁时的性能损耗(创建销毁性能无法优化)</li><li>避免资源多重占用(例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作)</li><li>单例模式可以在系统设置全局的访问点,优化和共享资源访问</li></ul><h3 id=缺点>缺点</h3><ul><li>拓展困难,因为一般没有接口(接口对单例模式没有意义)</li><li>不利于测试,在单例模式创建之前不能完成测试</li><li>与单一职责原则冲突</li></ul><h3 id=业务例子>业务例子</h3><div class=highlight><pre tabindex=0 class=chroma><code class=language-java data-lang=java><span class=line><span class=cl><span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 线程池
</span></span></span><span class=line><span class=cl><span class=cm> *
</span></span></span><span class=line><span class=cl><span class=cm> * @author robinson
</span></span></span><span class=line><span class=cl><span class=cm> * 2021/9/28 15:19
</span></span></span><span class=line><span class=cl><span class=cm> *
</span></span></span><span class=line><span class=cl><span class=cm> **/</span>
</span></span><span class=line><span class=cl><span class=nd>@Slf4j</span>
</span></span><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nc>ExecutorUtil</span> <span class=o>{</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 核心线程数
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>final</span> <span class=kt>int</span> <span class=n>THREAD_CORE_POOL_SIZE</span> <span class=o>=</span> <span class=mi>5</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 队列容量
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>final</span> <span class=kt>int</span> <span class=n>THREAD_QUEUE_CAPACITY</span> <span class=o>=</span> <span class=mi>1024</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=n>ThreadPoolExecutor</span> <span class=n>executor</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 私有构造方法,防止初始化
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=nf>ExecutorUtil</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 获取线程池
</span></span></span><span class=line><span class=cl><span class=cm> *
</span></span></span><span class=line><span class=cl><span class=cm> * @return ThreadPoolExecutor
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kd>synchronized</span> <span class=n>ThreadPoolExecutor</span> <span class=nf>getExecutor</span><span class=o>(</span><span class=n>String</span> <span class=n>threadPoolName</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>if</span> <span class=o>(</span><span class=kc>null</span> <span class=o>==</span> <span class=n>executor</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=n>ThreadFactory</span> <span class=n>threadFactory</span> <span class=o>=</span> <span class=k>new</span> <span class=n>ThreadFactoryBuilder</span><span class=o>().</span><span class=na>setNameFormat</span><span class=o>(</span><span class=n>threadPoolName</span> <span class=o>+</span> <span class=s>"-%d"</span><span class=o>).</span><span class=na>build</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=n>executor</span> <span class=o>=</span> <span class=k>new</span> <span class=n>ThreadPoolExecutor</span><span class=o>(</span><span class=n>THREAD_CORE_POOL_SIZE</span><span class=o>,</span> <span class=n>THREAD_CORE_POOL_SIZE</span><span class=o>,</span>
</span></span><span class=line><span class=cl> <span class=mi>0</span><span class=n>L</span><span class=o>,</span> <span class=n>TimeUnit</span><span class=o>.</span><span class=na>MILLISECONDS</span><span class=o>,</span>
</span></span><span class=line><span class=cl> <span class=c1>// 定义队列大小,防止占用内存过大
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>new</span> <span class=n>LinkedBlockingQueue</span><span class=o><>(</span><span class=n>THREAD_QUEUE_CAPACITY</span><span class=o>),</span>
</span></span><span class=line><span class=cl> <span class=n>threadFactory</span><span class=o>,</span>
</span></span><span class=line><span class=cl> <span class=c1>// 使用CallerRunsPolicy() 保证所有任务不被丢弃
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=k>new</span> <span class=n>ThreadPoolExecutor</span><span class=o>.</span><span class=na>CallerRunsPolicy</span><span class=o>());</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>executor</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span></code></pre></div><h3 id=其他实现>其他实现</h3><div class=highlight><pre tabindex=0 class=chroma><code class=language-java data-lang=java><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1>//懒汉式
</span></span></span><span class=line><span class=cl><span class=c1>//实现方式一:线程不安全
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=c1>//私有化的构造器
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>(){}</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=k>if</span><span class=o>(</span><span class=n>instance</span> <span class=o>==</span> <span class=kc>null</span><span class=o>){</span>
</span></span><span class=line><span class=cl> <span class=n>instance</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl><span class=c1>//实现方式二:线程安全
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=c1>//私有化的构造器
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>(){}</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=kd>synchronized</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=k>if</span><span class=o>(</span><span class=n>instance</span> <span class=o>==</span> <span class=kc>null</span><span class=o>){</span>
</span></span><span class=line><span class=cl> <span class=n>instance</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl><span class=c1>//实现方式三:双重检查锁→推荐
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=cm>/*
</span></span></span><span class=line><span class=cl><span class=cm> 多线程下,可能出现空指针问题,原因:JVM的优化和指令重排
</span></span></span><span class=line><span class=cl><span class=cm> 解决:volatile
</span></span></span><span class=line><span class=cl><span class=cm>*/</span>
</span></span><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=c1>//私有化的构造器
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>(){}</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>volatile</span> <span class=n>Singleton</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=k>if</span><span class=o>(</span><span class=n>instance</span> <span class=o>!=</span> <span class=kc>null</span><span class=o>){</span><span class=c1>//iyci判断,如果instance值不为空,不需要强占锁,直接返回对象
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>synchronized</span><span class=o>(</span><span class=n>Singleton</span><span class=o>.</span><span class=na>class</span><span class=o>){</span>
</span></span><span class=line><span class=cl> <span class=k>if</span><span class=o>(</span><span class=n>instance</span> <span class=o>==</span> <span class=kc>null</span><span class=o>){</span><span class=c1>//第二次判断
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=n>instance</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>instance</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1>//实现方式四:静态内部类→推荐
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=cm>/*
</span></span></span><span class=line><span class=cl><span class=cm> JVM加载外部类的过程中,不会加载静态内部类,只有内部类的属性、方法调用时才会被加载→解决指令重排问题
</span></span></span><span class=line><span class=cl><span class=cm>*/</span>
</span></span><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=c1>//私有化的构造器
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>(){}</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=n>clss</span> <span class=n>SingletonHoler</span><span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=c1>//内部类中声明并初始化外部类的对象
</span></span></span><span class=line><span class=cl><span class=c1></span> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>final</span> <span class=n>Singleton</span> <span class=n>INSTANCE</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>(){</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>SingletonHolder</span><span class=o>.</span><span class=na>INSTANCE</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1>// 解决序列化破坏
</span></span></span><span class=line><span class=cl><span class=c1></span><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>()</span> <span class=kd>implements</span> <span class=n>Serializable</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 私有化的构造器
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>()</span> <span class=o>{};</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>class</span> <span class=nc>SingletonHolder</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 内部类中声明并初始化外部类的对象
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>final</span> <span class=n>Singleton</span> <span class=n>INSTANCE</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>SingletonHolder</span><span class=o>.</span><span class=na>INSTANCE</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 当进行反序列化时,会自动调用该方法
</span></span></span><span class=line><span class=cl><span class=cm> * @return
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=n>Object</span> <span class=nf>readResolve</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>SingletonHolder</span><span class=o>.</span><span class=na>INSTANCE</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 解决序列化破坏
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl><span class=kd>public</span> <span class=kd>class</span> <span class=nf>Singleton</span><span class=o>(){</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kt>boolean</span> <span class=n>flag</span> <span class=o>=</span> <span class=kc>false</span><span class=o>;</span> <span class=c1>// 实际开发中会用加密过的一个标志
</span></span></span><span class=line><span class=cl><span class=c1></span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 私有化的构造器
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=nf>Singleton</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>if</span><span class=o>(</span><span class=n>flag</span><span class=o>)</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>throw</span> <span class=k>new</span> <span class=n>RuntimeException</span><span class=o>(</span><span class=s>"不能用反射破坏单例模式"</span><span class=o>);</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl> <span class=n>flag</span> <span class=o>=</span> <span class=kc>true</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>class</span> <span class=nc>SingletonHolder</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=cm>/**
</span></span></span><span class=line><span class=cl><span class=cm> * 内部类中声明并初始化外部类的对象
</span></span></span><span class=line><span class=cl><span class=cm> */</span>
</span></span><span class=line><span class=cl> <span class=kd>private</span> <span class=kd>static</span> <span class=kd>final</span> <span class=n>Singleton</span> <span class=n>INSTANCE</span> <span class=o>=</span> <span class=k>new</span> <span class=n>Singleton</span><span class=o>();</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl> <span class=kd>public</span> <span class=kd>static</span> <span class=n>Singleton</span> <span class=nf>getInstance</span><span class=o>()</span> <span class=o>{</span>
</span></span><span class=line><span class=cl> <span class=k>return</span> <span class=n>SingletonHolder</span><span class=o>.</span><span class=na>INSTANCE</span><span class=o>;</span>
</span></span><span class=line><span class=cl> <span class=o>}</span>
</span></span><span class=line><span class=cl><span class=o>}</span>
</span></span></code></pre></div><h3 id=总结>总结</h3><p>单例模式是23个模式中比较简单的模式,应用也非常广泛,如在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理这些Bean的生命期,决定什么时候创建出来,什么时候销毁,销毁的时候要如何处理,等等。如果采用非单例模式(Prototype类型),则Bean初始化后的管理交由J2EE容器,Spring容器不再跟踪管理Bean的生命周期</p><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article></section><article class="chapter deprecated"><h3 id=前端>前端</h3><h1 id=前端知识>前端知识</h1><ul><li>React</li><li>Vue</li><li>Typescript</li></ul><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><section><h1 class=a11y-only>前端 的子部分</h1><article class=default><h1 id=typescript>Typescript</h1><h3 id=typescript>Typescript</h3><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><section><h1 class=a11y-only>Typescript 的子部分</h1><article class=default><h1 id=ts常用用法>TS常用用法</h1><ol><li>arr 转map</li></ol><div class=highlight><pre tabindex=0 class=chroma><code class=language-typescript data-lang=typescript><span class=line><span class=cl><span class=kr>const</span> <span class=nx>arr</span> <span class=o>=</span> <span class=p>[</span>
</span></span><span class=line><span class=cl> <span class=p>{</span><span class=nx>metricsKey</span><span class=o>:</span> <span class=s1>'k-1'</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=o>:</span> <span class=s1>'v-1'</span><span class=p>},</span>
</span></span><span class=line><span class=cl> <span class=p>{</span><span class=nx>metricsKey</span><span class=o>:</span> <span class=s1>'k-2'</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=o>:</span> <span class=s1>'v-2'</span><span class=p>},</span>
</span></span><span class=line><span class=cl> <span class=p>{</span><span class=nx>metricsKey</span><span class=o>:</span> <span class=s1>'k-3'</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=o>:</span> <span class=s1>'v-3'</span><span class=p>},</span>
</span></span><span class=line><span class=cl> <span class=p>{</span><span class=nx>metricsKey</span><span class=o>:</span> <span class=s1>'k-4'</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=o>:</span> <span class=s1>'v-4'</span><span class=p>},</span>
</span></span><span class=line><span class=cl> <span class=p>{</span><span class=nx>metricsKey</span><span class=o>:</span> <span class=s1>'k-5'</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=o>:</span> <span class=s1>'v-5'</span><span class=p>},</span>
</span></span><span class=line><span class=cl><span class=p>]</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=kr>const</span> <span class=nx>map</span> <span class=o>=</span> <span class=k>new</span> <span class=nx>Map</span><span class=p><</span><span class=nt>string</span><span class=err>,</span> <span class=na>string</span><span class=p>>();</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nx>arr</span><span class=p>.</span><span class=nx>forEach</span><span class=p>(({</span><span class=nx>metricsKey</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=p>})</span> <span class=o>=></span> <span class=nx>map</span><span class=p>.</span><span class=kr>set</span><span class=p>(</span><span class=nx>metricsKey</span><span class=p>,</span> <span class=nx>metricsValue</span><span class=p>))</span>
</span></span></code></pre></div><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article></section><article class=default><h1 id=vue>Vue</h1><h3 id=vue>Vue</h3><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article><section><h1 class=a11y-only>Vue 的子部分</h1><article class=default><h1 id=vue知识点>Vue知识点</h1><h3 id=修饰符native-修饰什么时候使用>修饰符.native 修饰什么时候使用</h3><ul><li>在我们需要监听一个组件的原生事件时,必须给对应的事件加上.native 修饰符,才能进行监</li></ul><h3 id=事件总线>事件总线:</h3><div class=highlight><pre tabindex=0 class=chroma><code class=language-js data-lang=js><span class=line><span class=cl><span class=nx>Vue</span><span class=p>.</span><span class=nx>prototype</span><span class=p>.</span><span class=nx>$bus</span> <span class=o>=</span> <span class=k>new</span> <span class=nx>Vue</span><span class=p>();</span>
</span></span><span class=line><span class=cl><span class=k>this</span><span class=p>.</span><span class=nx>$bus</span><span class=p>.</span><span class=nx>$emit</span><span class=p>()</span>
</span></span><span class=line><span class=cl><span class=k>this</span><span class=p>.</span><span class=nx>$bus</span><span class=p>.</span><span class=nx>$on</span><span class=p>()</span>
</span></span></code></pre></div><footer class=footline><div id=comments><style>#comment{padding:8rem 0 2rem}#comment .vemoji{max-width:1.5em;max-height:1.5em}</style><div id=comment><script src=https://giscus.app/client.js data-repo=zhou-yi-git/zhou-yi-git.github.io data-repo-id=R_kgDOI0eMkg data-category=Announcements data-category-id=DIC_kwDOI0eMks4CT2cD data-mapping=pathname data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=zh-CN crossorigin=anonymous data-term=1046 async></script></div><noscript>Please enable JavaScript to view the comments powered by giscus.</noscript></div></footer></article></section></section></section></div></main></div><script src=./js/clipboard.min.js?1676435289 defer></script>
<script src=./js/perfect-scrollbar.min.js?1676435289 defer></script>
<script src=./js/featherlight.min.js?1676435289 defer></script>
<script src=./js/theme.js?1676435289 defer></script></body></html>