Skip to content

Commit d766e78

Browse files
committed
categorize all documents
1 parent 21220c1 commit d766e78

File tree

174 files changed

+193
-202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+193
-202
lines changed

doc/b/Chain-Of-Responsibility.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public class ATMApplication {
6868

6969
责任链模式建议我们将一块一块的逻辑(分配 100 元纸币、分配 50 元纸币等)封装成为多个对象,并且将这些对象按照顺序进行组织,成为一个处理请求对象的链条。这样我们就可以将请求投递给链条,请求在链条中按照顺序逐个传递,每一个处理对象可选择对请求处理或者不处理。此时出钞的过程如下图所示:
7070
<div align="center">
71-
<img src="/doc/resource/chain-of-responsibility/出钞过程示意图.jpg" width="90%"/>
71+
<img src="/res/chain-of-responsibility/出钞过程示意图.jpg" width="90%"/>
7272
</div>
7373

7474
从上图中,我们看出所有的组件(处理器)都有着两个共同的特点:分配对于面额的纸币、连接着后继处理器(尾处理器除外)。为了使所有的组件去差异化,我们应该对组件进行抽象,这样我们就可以使任意一个组件成为某个组件的后继,甚至可以随意调换他们之间的顺序。
@@ -78,17 +78,17 @@ public class ATMApplication {
7878
## 3.1 案例类图
7979
按照上面的思路,我们对系统进行重构,新的类图结构如下图所示。
8080
<div align="center">
81-
<img src="/doc/resource/chain-of-responsibility/案例类图.jpg" width="100%"/>
81+
<img src="/res/chain-of-responsibility/案例类图.jpg" width="100%"/>
8282
</div>
8383

8484
> 在应用启动时,通过`AbstractPaperPasCurrencyAllocator.nextAllocator()`提前构造好链路【`RMB100Allocator -> RMB50Allocator -> RMB10Allocator` 】。当用户发起兑换现金的请求后,请求首先到达 100 元的分配处理器。在该处理器分配完毕后,会根据请求中剩余的金额(`CurrencyRequest.toAllocateAmount`)决定是否继续向后继处理器传递请求,如此往复。直到请求从链路中脱离时,应用开始出钞(`CurrencyRequest.cashOut()`),如果全部金额正常分配,则为用户提供现金,否则告知用户系统无法提供本次服务。
8585
8686
## 3.2 代码附录
8787
<div align="center">
88-
<img src="/doc/resource/chain-of-responsibility/代码附录.png" width="95%"/>
88+
<img src="/res/chain-of-responsibility/代码附录.png" width="95%"/>
8989
</div>
9090

91-
代码层次及类说明如上所示,更多内容请参考[案例代码](/src/main/java/com/aoligei/behavioral/chain_of_responsibility)。ATM 应用示例代码如下
91+
代码层次及类说明如上所示,更多内容请参考[案例代码](/cases-behavioral/src/main/java/com/patterns/chain_of_responsibility)。ATM 应用示例代码如下
9292
```java
9393
public class ATMApplication {
9494

@@ -133,7 +133,7 @@ public class ATMApplication {
133133
## 4.2 类图分析
134134

135135
<div align="center">
136-
<img src="/doc/resource/chain-of-responsibility/经典责任链模式类图.jpg" width="60%"/>
136+
<img src="/res/chain-of-responsibility/经典责任链模式类图.jpg" width="60%"/>
137137
</div>
138138

139139
责任链模式的类图结构如上所示,在责任链模式中,有如下的参与角色:
@@ -186,7 +186,7 @@ public class ATMApplication {
186186
在责任链模式的类图分析处,我们提到 Handler 不一定非要提供一个设置后继处理器的接口。我们可以把链路的维护职责独立出来,这也是责任链模式的一个变种实现。这个变种的类图结构如下:
187187

188188
<div align="center">
189-
<img src="/doc/resource/chain-of-responsibility/责任链模式变种类图.jpg" width="80%"/>
189+
<img src="/res/chain-of-responsibility/责任链模式变种类图.jpg" width="80%"/>
190190
</div>
191191

192192
在这个类图结构中,整个链路由 HandlerChain 负责维护,提供了增加处理器,删除处理器等方法。除此之外,HandlerChain 本身也实现了处理器接口,在它的处理方法(handle)中,也负责请求在整个链路中的传递。它内部维护了当前的处理器在整个链路中的索引,在客户端发起一个请求后:
@@ -205,7 +205,7 @@ public class ATMApplication {
205205
在 servlet 规范中,约定了可以通过 Filter 在请求进入容器后,执行 Servlet.service() 方法之前,对 web 资源进行过滤,权限鉴别等处理。在 tomcat 启动时,会加载所有的过滤器信息。在 tomcat 收到请求时,再加载整个过滤器的链路,然后请求执行过滤器的链条,等请求从链路中脱离后,才会进入真正的业务接口。工作过程如下图所示:
206206

207207
<div align="center">
208-
<img src="/doc/resource/chain-of-responsibility/Filter工作过程示意图.jpg" width="80%"/>
208+
<img src="/res/chain-of-responsibility/Filter工作过程示意图.jpg" width="80%"/>
209209
</div>
210210

211211
在 tomcat 中,每一个 Filter 都是一个处理器,该处理器不仅能处理请求,还能处理响应。如上图,对于 request 来说,链路的结构为 FilterA -> FilterB -> FilterC,而对于响应来说,链路的结构为 FilterC -> FilterB -> FilterA。这种双向处理的思想很经典,经常能在各个框架中看到类似的实现。那么,是如何实现的呢?下面将简单分析一下源码。
@@ -361,7 +361,7 @@ public final class ApplicationFilterChain implements FilterChain {
361361
netty 中的 pipeline 则采用了双向链表的形式来组织所有处理器。netty 在设计上认为,对于入站的数据来说(收到的数据),给链路中的所有处理器都提供一个处理机会,出站同理(这里讨论的是 channel 提供的写出方法,对于 context 提供的并不适用)。在 netty 中,处理器的结构示意图如下:
362362

363363
<div align="center">
364-
<img src="/doc/resource/chain-of-responsibility/netty处理器结构示意图.jpg" width="90%"/>
364+
<img src="/res/chain-of-responsibility/netty处理器结构示意图.jpg" width="90%"/>
365365
</div>
366366

367367
netty 中,所有的处理器都继承自 ChannelHandler 接口,由该接口衍生出 ChannelInboundHandler 和 ChannelOutboundHandler,分别是入站数据处理器和出站数据处理器。他们分别为数据的入站和出站服务,当数据入站时,只有链路上的入站处理器会得到处理的机会;出站同理。
@@ -450,4 +450,4 @@ abstract class AbstractChannelHandlerContext implements
450450

451451

452452
# 附录
453-
[回到主页](/README.md)&emsp;[案例代码](/src/main/java/com/aoligei/behavioral/chain_of_responsibility)
453+
[回到主页](/README.md)&emsp;[案例代码](/cases-behavioral/src/main/java/com/patterns/chain_of_responsibility)

doc/b/Command.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public void button_click() {
4848
# 二、案例引入
4949
作为开发者,对 IDE 的使用应该并不陌生,如下图所示:
5050
<div align="center">
51-
<img src="/doc/resource/command/idea格式化代码.png" width="100%"/>
51+
<img src="/res/command/idea格式化代码.png" width="100%"/>
5252
</div>
5353

5454
我们常常在编辑代码时,都需要对类的代码进行格式化,这很简单,通过菜单中`Code -> Reformat Code`按钮即可完成。让我们来对该应用的职责进行划分:
@@ -70,7 +70,7 @@ public void button_click() {
7070
按照上面的分析,我们得出这样的职责划分和工作流程:
7171

7272
<div align="center">
73-
<img src="/doc/resource/command/案例职责划分.jpg" width="80%"/>
73+
<img src="/res/command/案例职责划分.jpg" width="80%"/>
7474
</div>
7575

7676
我们通过对请求过程进行解耦,对请求本身进行封装,得到了一个可以向未知的对象(文档对象由应用程序指定,按钮对象并不知道由谁来响应请求)发起一个可变的请求(按钮对象调用的是 Request 的 response() 方法,但按钮对象并不知道是哪一个具体的实现)的结构,而这就是命令模式的核心。
@@ -80,7 +80,7 @@ public void button_click() {
8080
### 3.1 案例类图
8181
这里已经为上述分析编写了一个简单的示例,提供了示例中提到的类对象,除此之外,还提供了一个客户端,用以模拟用户对菜单的点击。
8282
<div align="center">
83-
<img src="/doc/resource/command/案例类图.jpg" width="90%"/>
83+
<img src="/res/command/案例类图.jpg" width="90%"/>
8484
</div>
8585

8686
该案例的类图结构如上所示,由以下部分组成。
@@ -93,10 +93,10 @@ public void button_click() {
9393

9494
### 3.2 代码附录
9595
<div align="center">
96-
<img src="/doc/resource/command/代码附录.png" width="95%"/>
96+
<img src="/res/command/代码附录.png" width="95%"/>
9797
</div>
9898

99-
代码层次及类说明如上所示,更多内容请参考[案例代码](/src/main/java/com/aoligei/behavioral/command/ide)。客户端示例代码如下
99+
代码层次及类说明如上所示,更多内容请参考[案例代码](/cases-behavioral/src/main/java/com/patterns/command/ide)。客户端示例代码如下
100100
```java
101101
public class Client {
102102
public static void main(String[] args) {
@@ -128,7 +128,7 @@ public class Client {
128128
## 4.1 结构
129129
命令模式的通用类图如下所示:
130130
<div align="center">
131-
<img src="/doc/resource/command/经典命令模式类图.jpg" width="60%"/>
131+
<img src="/res/command/经典命令模式类图.jpg" width="60%"/>
132132
</div>
133133

134134
命令模式的参与者有如下:
@@ -214,10 +214,10 @@ public class Client {
214214
215215
该游戏的代码参见附录。游戏的运行效果如下所示:
216216
<div align="center">
217-
<img src="/doc/resource/command/gaming.gif" width="80%"/>
217+
<img src="/res/command/gaming.gif" width="80%"/>
218218
</div>
219219

220220
# 附录
221-
[回到主页](/README.md)&emsp;[案例代码](/src/main/java/com/aoligei/behavioral/command/ide)&emsp;[小猫摘星星代码](/src/main/java/com/aoligei/behavioral/command/game)
221+
[回到主页](/README.md)&emsp;[案例代码](/cases-behavioral/src/main/java/com/patterns/command/ide)&emsp;[小猫摘星星代码](/cases-behavioral/src/main/java/com/patterns/command/game)
222222

223223
推荐阅读文章:[Command Design Pattern in Java](https://www.journaldev.com/1624/command-design-pattern)

doc/b/Interpreter.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
> 在 java-web 开发中,很多时候我们并不能将一个后台接口直接暴露给所有登录的用户。我们希望保证某些后台接口的安全,只对拥有权限的请求开放接口,并且拦截掉那些不具备权限的请求。此时,我们可以借助 spring aop 提供的特性,以自定义注解形式标注这个权限范围的限定,在请求进入接口前,检查权限。比如,对于罗列所有系统用户的列表接口来说,访问他的权限范围为:当前用户拥有管理员的角色。接口定义如下图所示:
1010
1111
<div align="center">
12-
<img src="/doc/resource/interpreter/权限校验的接口示例.png" width="60%"/>
12+
<img src="/res/interpreter/权限校验的接口示例.png" width="60%"/>
1313
</div>
1414

1515
这是可行的,我们只需要在请求进入这个接口之前,检查当前登录的用户,如果用户不具备管理员的角色,拦截掉这个请求即可。但真实情况是,系统中对于权限的划分,远比我们想象的复杂。我们发现,某些特定的接口在权限要求时往往呈现多样性的态势。
@@ -24,7 +24,7 @@
2424
2525
按照这些规则,我们对于导出用户列表这个后台接口的权限范围表达式可以定义为:`(E:system.user.export-to-xlsx | E:system.user.export-to-docx) | R:admin`。此时,导出用户列表的接口定义如下所示:
2626
<div align="center">
27-
<img src="/doc/resource/interpreter/复杂的权限校验示例.png" width="80%"/>
27+
<img src="/res/interpreter/复杂的权限校验示例.png" width="80%"/>
2828
</div>
2929

3030
那么,我们该如何解析这个规则表达式?并且如何对一个规则表达式进行求解呢?
@@ -38,28 +38,28 @@
3838
3939
回顾我们定义的语法规则,其中包含了两类关于权限的表述:一类是某个具体的权限表达式(比如具备某个角色);另一类是承上启下的组织关系(比如并且关系 ),这些组织关系由一些符号代替,这里就称呼其为符号表达式。当符号表达式在组织多个权限表达式之间的关系时,只需要先计算两个邻近的权限表达式结果,将这个结果作为一个新的权限表达式和其他的权限表达式进行组织,如此反复即可。而优先级则确定了哪些符号表达式先执行,优先级规定了求解顺序。所以,只要有了这两类表述,并且知晓各个符号表达式的优先级,就能对整个表达式进行解释求值。求值过程大致如下图所示:
4040
<div align="center">
41-
<img src="/doc/resource/interpreter/案例执行流程.png" width="70%"/>
41+
<img src="/res/interpreter/案例执行流程.png" width="70%"/>
4242
</div>
4343

4444
不管是权限表达式,还是符号表达式,都具有完全一致的行为:得到一个 boolean 类型的值,从业务意义上来说,表示当前用户是否具有某个(些)权限。解释器模式建议我们对两种表达式类型进行行为统一,提供更高层次的抽象,这个抽象定义了解释表达式(片段)自身的行为。综上所述,类图结构设计如下:
4545

4646
<div align="center">
47-
<img src="/doc/resource/interpreter/案例类图.png" width="90%"/>
47+
<img src="/res/interpreter/案例类图.png" width="90%"/>
4848
</div>
4949

5050
> 如上类图所示,`Expression` 类为所有表达式类型的抽象,提供了鉴权的行为:`authenticate(String) boolean` ,参数为当前请求的用户 key。`PermissionExpression` 类为权限表达式,`type` 表示鉴权类型(如角色鉴权/页面元素鉴权),`auth` 表示权限 key(比如角色 admin、页面元素 system.user.export-to-docx等)。`AbstractSymbolExpression` 类为符号表达式,持有符号的前一个表达式对象和后一个表达式对象,分为 and 及 or 关系表达式。
5151
5252
如此一来,求解表达式就只需构造一个由各种表达式构建的解释器树即可。比如表达式`(E:system.user.export-to-xlsx | E:system.user.export-to-docx) | R:admin`,对应的解释器树如下所示:
5353
<div align="center">
54-
<img src="/doc/resource/interpreter/案例的解释器树.jpg" width="70%"/>
54+
<img src="/res/interpreter/案例的解释器树.jpg" width="70%"/>
5555
</div>
5656

5757
# 三、案例实现
5858
<div align="center">
59-
<img src="/doc/resource/interpreter/代码附录.png" width="95%"/>
59+
<img src="/res/interpreter/代码附录.png" width="95%"/>
6060
</div>
6161

62-
代码层次及类说明如上所示,更多内容请参考[案例代码](/src/main/java/com/aoligei/behavioral/interpreter)。客户端示例代码如下
62+
代码层次及类说明如上所示,更多内容请参考[案例代码](/cases-behavioral/src/main/java/com/patterns/interpreter)。客户端示例代码如下
6363
```java
6464
public class Client {
6565
public static void main(String[] args) {
@@ -138,7 +138,7 @@ public class Client {
138138

139139
## 4.2 通用类图分析
140140
<div align="center">
141-
<img src="/doc/resource/interpreter/经典解释器模式类图.jpg" width="60%"/>
141+
<img src="/res/interpreter/经典解释器模式类图.jpg" width="60%"/>
142142
</div>
143143

144144
解释器模式的通用类图结构如上图所示,在解释器模式中主要有如下参与者角色:
@@ -164,5 +164,5 @@ public class Client {
164164
在解释器模式中,我们并未提及如何构建一个抽象的语法树,这意味着解释器模式并不负责语法分析。抽象语法树可以用数据库表驱动的方式来生成,也可以采用语法分析程序(比如递归下降法)构建,甚至,可以由客户端直接构建(例如,`Client.buildExpressionForApi1()` 方法)。
165165

166166
# 附录
167-
[回到主页](/README.md)&emsp;[案例代码](/src/main/java/com/aoligei/behavioral/interpreter)
167+
[回到主页](/README.md)&emsp;[案例代码](/cases-behavioral/src/main/java/com/patterns/interpreter)
168168

0 commit comments

Comments
 (0)