forked from iluwatar/java-design-patterns
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
translation: Added Chinese Translation for Combinator and Monitor pat…
…terns (iluwatar#2703) * Create combinator * translation for combinator and monitor to Chinese
- Loading branch information
1 parent
a984449
commit 02e6d0f
Showing
4 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
--- | ||
title: Combinator | ||
category: Idiom | ||
language: zh | ||
tag: | ||
- Reactive | ||
--- | ||
|
||
## 或称 | ||
|
||
构图模式 | ||
|
||
## 目的 | ||
|
||
功能模式代表了一种以组合功能为中心的图书馆组织风格。 | ||
简单地说,有一些类型 T,一些用于构造类型 T 的“原始”值的函数,以及一些可以以各种方式组合类型 T 的值以构建更复杂的类型 T 值的“组合器”。 | ||
|
||
## 解释 | ||
|
||
真实世界例子 | ||
|
||
> 在计算机科学中,组合逻辑被用作计算的简化模型,用于可计算性理论和证明理论。 尽管组合逻辑很简单,但它捕获了计算的许多基本特征。 | ||
> | ||
通俗的说 | ||
> 组合器允许从先前定义的“事物”创建新的“事物”。 | ||
> | ||
维基百科说 | ||
|
||
> 组合器是一个高阶函数,仅使用函数应用程序和之前定义的组合器来定义其参数的结果。 | ||
> | ||
**程序示例** | ||
|
||
翻译上面的组合器示例。 首先,我们有一个由几个方法`contains`, `not`, `or`, `and`组成的接口。 | ||
|
||
```java | ||
// 用于查找文本中的行的功能界面。 | ||
public interface Finder { | ||
|
||
// 在文本中查找行的函数。 | ||
List<String> find(String text); | ||
|
||
// 函数{@link #find(String)}的简单实现。 | ||
static Finder contains(String word) { | ||
return txt -> Stream.of(txt.split("\n")) | ||
.filter(line -> line.toLowerCase().contains(word.toLowerCase())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
// 组合器:not。 | ||
default Finder not(Finder notFinder) { | ||
return txt -> { | ||
List<String> res = this.find(txt); | ||
res.removeAll(notFinder.find(txt)); | ||
return res; | ||
}; | ||
} | ||
|
||
// 组合器:or。 | ||
default Finder or(Finder orFinder) { | ||
return txt -> { | ||
List<String> res = this.find(txt); | ||
res.addAll(orFinder.find(txt)); | ||
return res; | ||
}; | ||
} | ||
|
||
// 组合器:and。 | ||
default Finder and(Finder andFinder) { | ||
return | ||
txt -> this | ||
.find(txt) | ||
.stream() | ||
.flatMap(line -> andFinder.find(line).stream()) | ||
.collect(Collectors.toList()); | ||
} | ||
... | ||
} | ||
``` | ||
|
||
然后我们还有另一个组合器用于一些复杂的查找器`advancedFinder`, `filteredFinder`, `specializedFinder`和`expandedFinder`。 | ||
|
||
```java | ||
// 由简单取景器组成的复杂取景器。 | ||
public class Finders { | ||
|
||
private Finders() { | ||
} | ||
|
||
// Finder 用于查找复杂的查询。 | ||
public static Finder advancedFinder(String query, String orQuery, String notQuery) { | ||
return | ||
Finder.contains(query) | ||
.or(Finder.contains(orQuery)) | ||
.not(Finder.contains(notQuery)); | ||
} | ||
|
||
// 过滤查找器也会查找包含排除查询的查询。 | ||
public static Finder filteredFinder(String query, String... excludeQueries) { | ||
var finder = Finder.contains(query); | ||
|
||
for (String q : excludeQueries) { | ||
finder = finder.not(Finder.contains(q)); | ||
} | ||
return finder; | ||
} | ||
|
||
// 专门查询。 每个下一个查询都会在上一个结果中查找。 | ||
public static Finder specializedFinder(String... queries) { | ||
var finder = identMult(); | ||
|
||
for (String query : queries) { | ||
finder = finder.and(Finder.contains(query)); | ||
} | ||
return finder; | ||
} | ||
|
||
// 扩展查询。 寻找替代品。 | ||
public static Finder expandedFinder(String... queries) { | ||
var finder = identSum(); | ||
|
||
for (String query : queries) { | ||
finder = finder.or(Finder.contains(query)); | ||
} | ||
return finder; | ||
} | ||
... | ||
} | ||
``` | ||
|
||
现在我们已经创建了组合器的接口和方法。 现在我们有一个处理这些组合器的应用程序。 | ||
|
||
```java | ||
var queriesOr = new String[]{"many", "Annabel"}; | ||
var finder = Finders.expandedFinder(queriesOr); | ||
var res = finder.find(text()); | ||
LOGGER.info("the result of expanded(or) query[{}] is {}", queriesOr, res); | ||
|
||
var queriesAnd = new String[]{"Annabel", "my"}; | ||
finder = Finders.specializedFinder(queriesAnd); | ||
res = finder.find(text()); | ||
LOGGER.info("the result of specialized(and) query[{}] is {}", queriesAnd, res); | ||
|
||
finder = Finders.advancedFinder("it was", "kingdom", "sea"); | ||
res = finder.find(text()); | ||
LOGGER.info("the result of advanced query is {}", res); | ||
|
||
res = Finders.filteredFinder(" was ", "many", "child").find(text()); | ||
LOGGER.info("the result of filtered query is {}", res); | ||
|
||
private static String text() { | ||
return | ||
"It was many and many a year ago,\n" | ||
+ "In a kingdom by the sea,\n" | ||
+ "That a maiden there lived whom you may know\n" | ||
+ "By the name of ANNABEL LEE;\n" | ||
+ "And this maiden she lived with no other thought\n" | ||
+ "Than to love and be loved by me.\n" | ||
+ "I was a child and she was a child,\n" | ||
+ "In this kingdom by the sea;\n" | ||
+ "But we loved with a love that was more than love-\n" | ||
+ "I and my Annabel Lee;\n" | ||
+ "With a love that the winged seraphs of heaven\n" | ||
+ "Coveted her and me."; | ||
} | ||
``` | ||
|
||
**程序输出:** | ||
|
||
```java | ||
the result of expanded(or) query[[many, Annabel]] is [It was many and many a year ago,, By the name of ANNABEL LEE;, I and my Annabel Lee;] | ||
the result of specialized(and) query[[Annabel, my]] is [I and my Annabel Lee;] | ||
the result of advanced query is [It was many and many a year ago,] | ||
the result of filtered query is [But we loved with a love that was more than love-] | ||
``` | ||
|
||
现在我们可以设计我们的应用程序,使其具有查询查找功能`expandedFinder`, `specializedFinder`, `advancedFinder`, `filteredFinder`,这些功能均派生自`contains`, `or`, `not`, `and`。 | ||
|
||
|
||
## 类图 | ||
![alt text](./etc/combinator.urm.png "Combinator class diagram") | ||
|
||
## 适用性 | ||
在以下情况下使用组合器模式: | ||
|
||
- 您可以从更简单的值创建更复杂的值,但具有相同的类型(它们的组合) | ||
|
||
## 好处 | ||
|
||
- 从开发人员的角度来看,API 由领域中的术语组成。 | ||
- 组合阶段和应用阶段之间有明显的区别。 | ||
- 首先构造一个实例,然后执行它。 | ||
- 这使得该模式适用于并行环境。 | ||
|
||
|
||
## 现实世界的例子 | ||
|
||
- java.util.function.Function#compose | ||
- java.util.function.Function#andThen | ||
|
||
## 鸣谢 | ||
|
||
- [Example for java](https://gtrefs.github.io/code/combinator-pattern/) | ||
- [Combinator pattern](https://wiki.haskell.org/Combinator_pattern) | ||
- [Combinatory logic](https://wiki.haskell.org/Combinatory_logic) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
title: Monitor | ||
category: Concurrency | ||
language: zh | ||
tag: | ||
- Performance | ||
--- | ||
|
||
## 或称 | ||
|
||
监控对象模式 | ||
|
||
## 目的 | ||
|
||
主要目的是为多个线程或进程提供一种结构化和受控的方式来安全地访问和操作共享资源,例如变量、数据结构或代码的关键部分,而不会导致冲突或竞争条件。 | ||
|
||
## 解释 | ||
|
||
通俗的说 | ||
|
||
> 监视器模式用于强制对数据进行单线程访问。 一次只允许一个线程在监视器对象内执行代码。 | ||
维基百科说 | ||
|
||
> 在并发编程(也称为并行编程)中,监视器是一种同步构造,它允许线程具有互斥性和等待(阻止)特定条件变为假的能力。 监视器还具有向其他线程发出信号通知其条件已满足的机制。 | ||
**程序示例** | ||
|
||
考虑有一家银行通过转账方式将钱从一个帐户转移到另一个帐户。 它是`同步`意味着只有一个线程可以访问此方法,因为如果许多线程访问它并在同一时间将资金从一个帐户转移到另一个帐户,则余额会发生变化! | ||
|
||
``` | ||
class Bank { | ||
private int[] accounts; | ||
Logger logger; | ||
public Bank(int accountNum, int baseAmount, Logger logger) { | ||
this.logger = logger; | ||
accounts = new int[accountNum]; | ||
Arrays.fill(accounts, baseAmount); | ||
} | ||
public synchronized void transfer(int accountA, int accountB, int amount) { | ||
if (accounts[accountA] >= amount) { | ||
accounts[accountB] += amount; | ||
accounts[accountA] -= amount; | ||
logger.info("Transferred from account :" + accountA + " to account :" + accountB + " , amount :" + amount + " . balance :" + getBalance()); | ||
} | ||
} | ||
``` | ||
|
||
getBalance 始终返回总金额,并且每次转账后总金额应相同 | ||
|
||
``` | ||
private synchronized int getBalance() { | ||
int balance = 0; | ||
for (int account : accounts) { | ||
balance += account; | ||
} | ||
return balance; | ||
} | ||
} | ||
``` | ||
|
||
## 类图 | ||
![alt text](./etc/monitor.urm.png "Monitor class diagram") | ||
|
||
## 适用性 | ||
|
||
监视器设计模式应该用于具有需要由多个线程或进程同时访问和操作的共享资源的情况。 此模式在需要同步以防止竞争条件、数据损坏和不一致状态的情况下特别有用。 以下是您应该考虑使用监视器模式的一些情况: | ||
|
||
1. **共享数据**:当您的应用程序涉及需要由多个线程访问和更新的共享数据结构、变量或资源时。 监视器确保一次只有一个线程可以访问共享资源,从而防止冲突并确保数据一致性。 | ||
|
||
2. **关键部分**:当您有代码的关键部分一次只需要由一个线程执行时。 关键部分是操作共享资源的代码部分,并发访问可能会导致问题。 监视器有助于确保在任何给定时间只有一个线程可以执行关键部分。 | ||
|
||
3. **线程安全**:当您需要确保线程安全而不是仅仅依赖锁和信号量等低级同步机制时。 监视器提供了封装同步和资源管理的更高级别的抽象。 | ||
|
||
4. **等待和发信号**:当您遇到线程需要等待满足某些条件才能继续操作时。 监视器通常包含线程等待特定条件以及其他线程在满足条件时通知它们的机制。 | ||
|
||
5. **死锁预防**:当您希望通过提供结构化方式来获取和释放共享资源上的锁来防止死锁时。 监视器通过确保资源访问得到良好管理来帮助避免常见的死锁情况。 | ||
|
||
6. **并发数据结构**:当您实现并发数据结构(例如队列、堆栈或哈希表)时,多个线程需要操作该结构,同时保持其完整性。 | ||
|
||
7. **资源共享**:当多个线程需要共享有限的资源时,例如连接数据库或访问网络套接字。 监视器可以帮助以受控方式管理这些资源的分配和释放。 | ||
|
||
8. **改进可维护性**:当您想要将同步逻辑和共享资源管理封装在单个对象中时,改进代码组织并使并发相关代码更容易推理。 | ||
|
||
但是,需要注意的是,监视器模式可能并不最适合所有并发场景。 在某些情况下,其他同步机制(例如锁、信号量或并发数据结构)可能更合适。 此外,现代编程语言和框架通常提供更高级别的并发结构,抽象出低级别同步的复杂性。 | ||
|
||
在应用监视器模式之前,建议彻底分析应用程序的并发需求,并选择最适合您需求的同步方法,同时考虑性能、复杂性和可用语言功能等因素。 | ||
|
||
## 相关模式 | ||
|
||
* Active object | ||
* Double-checked locking |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.