Skip to content

Commit 1e10951

Browse files
sudowandererMike
and
Mike
authored
Translation zh (iluwatar#1597)
* add state and callback pattern * add command and template-method pattern * add iterator pattern Co-authored-by: Mike <admin@xiaod.info>
1 parent f3c876e commit 1e10951

File tree

5 files changed

+766
-0
lines changed

5 files changed

+766
-0
lines changed

zh/callback/README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
layout: pattern
3+
title: Callback
4+
folder: callback
5+
permalink: /patterns/callback/
6+
categories: Idiom
7+
tags:
8+
- Reactive
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+
```java
34+
public interface Callback {
35+
36+
void call();
37+
}
38+
```
39+
40+
下面我们定义一个任务它将在任务执行完成后执行回调。
41+
42+
```java
43+
public abstract class Task {
44+
45+
final void executeWith(Callback callback) {
46+
execute();
47+
Optional.ofNullable(callback).ifPresent(Callback::call);
48+
}
49+
50+
public abstract void execute();
51+
}
52+
53+
public final class SimpleTask extends Task {
54+
55+
private static final Logger LOGGER = getLogger(SimpleTask.class);
56+
57+
@Override
58+
public void execute() {
59+
LOGGER.info("Perform some important activity and after call the callback method.");
60+
}
61+
}
62+
```
63+
64+
最后这里是我们如何执行一个任务然后接收一个回调当它完成时。
65+
66+
```java
67+
var task = new SimpleTask();
68+
task.executeWith(() -> LOGGER.info("I'm done now."));
69+
```
70+
## 类图
71+
![alt text](../../callback/etc/callback.png "Callback")
72+
73+
## 适用性
74+
使用回调模式当
75+
* 当一些同步或异步架构动作必须在一些定义好的活动执行后执行时。
76+
77+
## Java例子
78+
79+
* [CyclicBarrier](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html#CyclicBarrier%28int,%20java.lang.Runnable%29) 构造函数可以接受回调,该回调将在每次障碍被触发时触发。

zh/command/README.md

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
layout: pattern
3+
title: Command
4+
folder: command
5+
permalink: /patterns/command/
6+
categories: Behavioral
7+
tags:
8+
- Gang of Four
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+
```java
35+
public class Wizard {
36+
37+
private static final Logger LOGGER = LoggerFactory.getLogger(Wizard.class);
38+
39+
private final Deque<Command> undoStack = new LinkedList<>();
40+
private final Deque<Command> redoStack = new LinkedList<>();
41+
42+
public Wizard() {}
43+
44+
public void castSpell(Command command, Target target) {
45+
LOGGER.info("{} casts {} at {}", this, command, target);
46+
command.execute(target);
47+
undoStack.offerLast(command);
48+
}
49+
50+
public void undoLastSpell() {
51+
if (!undoStack.isEmpty()) {
52+
var previousSpell = undoStack.pollLast();
53+
redoStack.offerLast(previousSpell);
54+
LOGGER.info("{} undoes {}", this, previousSpell);
55+
previousSpell.undo();
56+
}
57+
}
58+
59+
public void redoLastSpell() {
60+
if (!redoStack.isEmpty()) {
61+
var previousSpell = redoStack.pollLast();
62+
undoStack.offerLast(previousSpell);
63+
LOGGER.info("{} redoes {}", this, previousSpell);
64+
previousSpell.redo();
65+
}
66+
}
67+
68+
@Override
69+
public String toString() {
70+
return "Wizard";
71+
}
72+
}
73+
```
74+
75+
接下来我们介绍咒语层级
76+
77+
```java
78+
public interface Command {
79+
80+
void execute(Target target);
81+
82+
void undo();
83+
84+
void redo();
85+
86+
String toString();
87+
}
88+
89+
public class InvisibilitySpell implements Command {
90+
91+
private Target target;
92+
93+
@Override
94+
public void execute(Target target) {
95+
target.setVisibility(Visibility.INVISIBLE);
96+
this.target = target;
97+
}
98+
99+
@Override
100+
public void undo() {
101+
if (target != null) {
102+
target.setVisibility(Visibility.VISIBLE);
103+
}
104+
}
105+
106+
@Override
107+
public void redo() {
108+
if (target != null) {
109+
target.setVisibility(Visibility.INVISIBLE);
110+
}
111+
}
112+
113+
@Override
114+
public String toString() {
115+
return "Invisibility spell";
116+
}
117+
}
118+
119+
public class ShrinkSpell implements Command {
120+
121+
private Size oldSize;
122+
private Target target;
123+
124+
@Override
125+
public void execute(Target target) {
126+
oldSize = target.getSize();
127+
target.setSize(Size.SMALL);
128+
this.target = target;
129+
}
130+
131+
@Override
132+
public void undo() {
133+
if (oldSize != null && target != null) {
134+
var temp = target.getSize();
135+
target.setSize(oldSize);
136+
oldSize = temp;
137+
}
138+
}
139+
140+
@Override
141+
public void redo() {
142+
undo();
143+
}
144+
145+
@Override
146+
public String toString() {
147+
return "Shrink spell";
148+
}
149+
}
150+
```
151+
152+
最后我们有咒语的目标地精。
153+
154+
```java
155+
public abstract class Target {
156+
157+
private static final Logger LOGGER = LoggerFactory.getLogger(Target.class);
158+
159+
private Size size;
160+
161+
private Visibility visibility;
162+
163+
public Size getSize() {
164+
return size;
165+
}
166+
167+
public void setSize(Size size) {
168+
this.size = size;
169+
}
170+
171+
public Visibility getVisibility() {
172+
return visibility;
173+
}
174+
175+
public void setVisibility(Visibility visibility) {
176+
this.visibility = visibility;
177+
}
178+
179+
@Override
180+
public abstract String toString();
181+
182+
public void printStatus() {
183+
LOGGER.info("{}, [size={}] [visibility={}]", this, getSize(), getVisibility());
184+
}
185+
}
186+
187+
public class Goblin extends Target {
188+
189+
public Goblin() {
190+
setSize(Size.NORMAL);
191+
setVisibility(Visibility.VISIBLE);
192+
}
193+
194+
@Override
195+
public String toString() {
196+
return "Goblin";
197+
}
198+
199+
}
200+
```
201+
202+
最后是整个示例的实践。
203+
204+
```java
205+
var wizard = new Wizard();
206+
var goblin = new Goblin();
207+
goblin.printStatus();
208+
// Goblin, [size=normal] [visibility=visible]
209+
wizard.castSpell(new ShrinkSpell(), goblin);
210+
// Wizard casts Shrink spell at Goblin
211+
goblin.printStatus();
212+
// Goblin, [size=small] [visibility=visible]
213+
wizard.castSpell(new InvisibilitySpell(), goblin);
214+
// Wizard casts Invisibility spell at Goblin
215+
goblin.printStatus();
216+
// Goblin, [size=small] [visibility=invisible]
217+
wizard.undoLastSpell();
218+
// Wizard undoes Invisibility spell
219+
goblin.printStatus();
220+
// Goblin, [size=small] [visibility=visible]
221+
```
222+
223+
## 类图
224+
![alt text](../../command/etc/command.png "Command")
225+
226+
## 适用性
227+
使用命令模式当你想
228+
229+
* 通过操作将对象参数化。您可以使用回调函数(即,已在某处注册以便稍后调用的函数)以过程语言表示这种参数化。命令是回调的一种面向对象替代方案。
230+
* 在不同的时间指定,排队和执行请求。一个命令对象的生存期可以独立于原始请求。如果请求的接收方可以以地址空间无关的方式来表示,那么你可以将请求的命令对象传输到其他进程并在那里执行请求。
231+
* 支持撤销。命令的执行操作可以在命令本身中存储状态以反转其效果。命令接口必须有添加的反执行操作,该操作可以逆转上一次执行调用的效果。执行的命令存储在历史列表中。无限撤消和重做通过分别向后和向前遍历此列表来实现,分别调用unexecute和execute。
232+
* 支持日志记录更改,以便在系统崩溃时可以重新应用它们。通过使用加载和存储操作扩展命令接口,你可以保留更改的永久日志。从崩溃中恢复涉及从磁盘重新加载记录的命令,并通过执行操作重新执行它们。
233+
* 通过原始的操作来构建一个以高级操作围绕的系统。这种结构在支持事务的信息系统中很常见。事务封装了一组数据更改。命令模式提供了一种对事务进行建模的方法。命令具有公共接口,让你以相同的方式调用所有事务。该模式还可以通过新的事务来轻松扩展系统。
234+
235+
## 典型用例
236+
237+
* 保留请求历史
238+
* 实现回调功能
239+
* 实现撤销功能
240+
241+
## Java世界例子
242+
243+
* [java.lang.Runnable](http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html)
244+
* [org.junit.runners.model.Statement](https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runners/model/Statement.java)
245+
* [Netflix Hystrix](https://github.com/Netflix/Hystrix/wiki)
246+
* [javax.swing.Action](http://docs.oracle.com/javase/8/docs/api/javax/swing/Action.html)
247+
248+
## 鸣谢
249+
250+
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
251+
* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
252+
* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
253+
* [J2EE Design Patterns](https://www.amazon.com/gp/product/0596004273/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596004273&linkCode=as2&tag=javadesignpat-20&linkId=f27d2644fbe5026ea448791a8ad09c94)

0 commit comments

Comments
 (0)