docs: Translation for zh (#1805)

* add state and callback pattern

* add command and template-method pattern

* add iterator pattern

* add bridege and DI pattern

* fix issue #1600

* add converter,proxy,visitor pattern

* add caching,composite,delegation,dirty-flag,interpreter patterns

* add dao and producer-consumer

* add dto and provate class data pattern

* fix #1646 png path problems

* fix #1646 composite png path case problem

* add abstract document pattern and version-number pattern

* add ambassador pattern

* add acyclic-visitor and api-gateway pattern

* add abstract-factory pattern

* add active-object pattern

* add aggregator-microservices and arrange-act-assert pattern

* update async-method-invocation pattern

* add balking and business-delegate pattern

* add bytecode and circuit-break pattern

* update arrange/act/assert pattern problems

* add csch pattern

* add language code, correct pic path

* #1805 update permalink

Co-authored-by: Subhrodip Mohanta <subhrodipmohanta@gmail.com>
Co-authored-by: Mike <admin@xiaod.info>
Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
This commit is contained in:
Mike Liu 2021-08-01 22:55:54 +08:00 committed by GitHub
parent d36efdbc7c
commit c5a4068e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 595 additions and 221 deletions

View File

@ -2,7 +2,7 @@
layout: pattern
title: Abstract Document
folder: abstract-document
permalink: /patterns/abstract-document/zh
permalink: /patterns/abstract-document/
categories: Structural
language: zh
tags:
@ -166,7 +166,7 @@ public class Car extends AbstractDocument implements HasModel, HasPrice, HasPart
## 类图
![alt text](../../abstract-document/etc/abstract-document.png "Abstract Document Traits and Domain")
![alt text](../../../abstract-document/etc/abstract-document.png "Abstract Document Traits and Domain")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Abstract Factory
folder: abstract-factory
permalink: /patterns/abstract-factory/zh
permalink: /patterns/abstract-factory/
categories: Creational
language: zh
tags:
@ -168,7 +168,7 @@ public static void main(String[] args) {
## 类图
![alt text](../../abstract-factory/etc/abstract-factory.urm.png "Abstract Factory class diagram")
![alt text](../../../abstract-factory/etc/abstract-factory.urm.png "Abstract Factory class diagram")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Active Object
folder: active-object
permalink: /patterns/active-object/zh
permalink: /patterns/active-object/
categories: Concurrency
language: zh
tags:
@ -122,4 +122,4 @@ public class Orc extends ActiveCreature {
## 类图
![alt text](../../active-object/etc/active-object.urm.PNG "Active Object class diagram")
![alt text](../../../active-object/etc/active-object.urm.PNG "Active Object class diagram")

View File

@ -2,7 +2,7 @@
layout: pattern
title: Acyclic Visitor
folder: acyclic-visitor
permalink: /patterns/acyclic-visitor/zh
permalink: /patterns/acyclic-visitor/
categories: Behavioral
language: zh
tags:
@ -123,7 +123,7 @@ public class ConfigureForUnixVisitor implements ZoomVisitor {
## 类图
![alt text](../../acyclic-visitor/etc/acyclic-visitor.png "Acyclic Visitor")
![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png "Acyclic Visitor")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Adapter
folder: adapter
permalink: /patterns/adapter/zh
permalink: /patterns/adapter/
categories: Structural
language: zh
tags:
@ -94,7 +94,7 @@ captain.row();
```
## 类图
![alt text](../../adapter/etc/adapter.urm.png "Adapter class diagram")
![alt text](../../../adapter/etc/adapter.urm.png "Adapter class diagram")
## 应用

View File

@ -2,7 +2,7 @@
layout: pattern
title: Aggregator Microservices
folder: aggregator-microservices
permalink: /patterns/aggregator-microservices/zh
permalink: /patterns/aggregator-microservices/
categories: Architectural
language: zh
tags:
@ -95,7 +95,7 @@ curl http://localhost:50004/product
## 类图
![alt text](../../aggregator-microservices/aggregator-service/etc/aggregator-service.png "Aggregator Microservice")
![alt text](../../../aggregator-microservices/aggregator-service/etc/aggregator-service.png "Aggregator Microservice")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Ambassador
folder: ambassador
permalink: /patterns/ambassador/zh
permalink: /patterns/ambassador/
categories: Structural
language: zh
tags:
@ -167,7 +167,7 @@ Service result: -1
## 类图
![alt text](../../ambassador/etc/ambassador.urm.png "Ambassador class diagram")
![alt text](../../../ambassador/etc/ambassador.urm.png "Ambassador class diagram")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: API Gateway
folder: api-gateway
permalink: /patterns/api-gateway/zh
permalink: /patterns/api-gateway/
categories: Architectural
language: zh
tags:
@ -123,7 +123,7 @@ public class ApiGateway {
```
## 类图
![alt text](../../api-gateway/etc/api-gateway.png "API Gateway")
![alt text](../../../api-gateway/etc/api-gateway.png "API Gateway")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Arrange/Act/Assert
folder: arrange-act-assert
permalink: /patterns/arrange-act-assert/zh
permalink: /patterns/arrange-act-assert/
categories: Idiom
language: zh
tags:
@ -73,10 +73,7 @@ public class Cash {
}
```
Then we write our unit tests according to Arrange/Act/Assert pattern. Notice the clearly
separated steps for each unit test.
然后我们根据Arrange / Act / Assert模式编写单元测试。 注意每个单元测试的步骤是分开的清晰的。
然后我们根据安排/ 执行 / 断言模式编写单元测试。 注意每个单元测试的步骤是分开的清晰的。
```java
class CashAAATest {
@ -129,9 +126,8 @@ class CashAAATest {
## 适用性
使用 Arrange/Act/Assert 模式当
使用 安排/执行/断言 模式当
* You need to structure your unit tests so that they're easier to read, maintain, and enhance.
* 你需要结构化你的单元测试代码这样它们可以更好的阅读,维护和增强。
## 鸣谢

View File

@ -4,33 +4,32 @@ title: Async Method Invocation
folder: async-method-invocation
permalink: /patterns/async-method-invocation/
categories: Concurrency
language: zh
tags:
- Reactive
---
## 含义
## 意图
异步方法是一种调用线程在等待任务结果时候不会被阻塞的模式。该模式提供了对多个任务的并行处理,并通过回调或等待,在所有任务完成后在提供结果读取
异步方法调用是一个调用线程在等待任务结果时不会阻塞的模式。模式为多个独立的任务提供并行的处理方式并且通过回调或等到它们全部完成来接收任务结果
## 解释
真实世界
真实世界例
> 发射太空火箭是一项令人兴奋的事业。在任务指挥部下达发射命令后, 经过一些未确定的时间,火箭要么成功发射,要么重演挑战者悲剧
> 发射火箭是一项令人激动的事务。任务指挥官发出了发射命令,经过一段不确定的时间后,火箭要么成功发射,要么惨遭失败
简而言之
通俗地说
> 异步方法调用开始任务处理并,在任务结果准备好之前立即返回。任务处理的结果会在稍后再返回给调用者
> 异步方法调用开始任务处理,并在任务完成之前立即返回。 任务处理的结果稍后返回给调用方
维基百科的解释
维基百科
> 在多线程计算机编程中异步方法调用AMI被称为异步方法调用或异步模式。这是一种设计模式,在这种模式下,调用点在等待被调用代码完成时不会被阻塞。相反,当返回点到达时,调用线程会得到通知。轮询结果是一种不受欢迎的选择
> 在多线程计算机编程中异步方法调用AMI称为异步方法调用或异步模式,是一种设计模式,其中在等待被调用的代码完成时不会阻塞调用站点。 而是在执行结果到达时通知调用线程。轮询调用结果是不希望的选项
**程示例**
**程示例**
在这个例子中,我们正在发射太空火箭和部署月球车。
该应用演示了异步方法调用模式。该模式的关键部分是 `AsyncResult`,它是一个异步计算值的中间容器,`AsyncCallback` 可以在任务完成时提供执行行动作,`AsyncExecutor` 负责管理异步任务的执行。
在此示例中,我们正在发射太空火箭并部署月球漫游车。该应用演示了异步方法调用模式。 模式的关键部分是`AsyncResult`(用于异步评估值的中间容器),`AsyncCallback`(可以在任务完成时被执行)和`AsyncExecutor`(用于管理异步任务的执行)。
```java
public interface AsyncResult<T> {
@ -54,7 +53,7 @@ public interface AsyncExecutor {
}
```
`ThreadAsyncExecutor``AsyncExecutor` 的一个实现。接下来将着重说明它的一些关键部分。
`ThreadAsyncExecutor``AsyncExecutor`的实现。 接下来将突出显示其一些关键部分。
```java
public class ThreadAsyncExecutor implements AsyncExecutor {
@ -91,14 +90,14 @@ public class ThreadAsyncExecutor implements AsyncExecutor {
}
```
然后我们准备发射一些火箭,看看所有东西是如何一起运作的。
然后,我们准备发射一些火箭,看看一切是如何协同工作的。
```java
public static void main(String[] args) throws Exception {
// construct a new executor that will run async tasks
// 构造一个将执行异步任务的新执行程序
var executor = new ThreadAsyncExecutor();
// start few async tasks with varying processing times, two last with callback handlers
// 以不同的处理时间开始一些异步任务,最后两个使用回调处理程序
final var asyncResult1 = executor.startProcess(lazyval(10, 500));
final var asyncResult2 = executor.startProcess(lazyval("test", 300));
final var asyncResult3 = executor.startProcess(lazyval(50L, 700));
@ -106,11 +105,11 @@ public static void main(String[] args) throws Exception {
final var asyncResult5 =
executor.startProcess(lazyval("callback", 600), callback("Deploying lunar rover"));
// emulate processing in the current thread while async tasks are running in their own threads
Thread.sleep(350); // Oh boy, we are working hard here
// 在当前线程中模拟异步任务正在它们自己的线程中执行
Thread.sleep(350); // 哦,兄弟,我们在这很辛苦
log("Mission command is sipping coffee");
// wait for completion of the tasks
// 等待任务完成
final var result1 = executor.endProcess(asyncResult1);
final var result2 = executor.endProcess(asyncResult2);
final var result3 = executor.endProcess(asyncResult3);
@ -118,13 +117,14 @@ public static void main(String[] args) throws Exception {
asyncResult5.await();
// log the results of the tasks, callbacks log immediately when complete
// 记录任务结果的日志, 回调的日志会在回调完成时立刻记录
log("Space rocket <" + result1 + "> launch complete");
log("Space rocket <" + result2 + "> launch complete");
log("Space rocket <" + result3 + "> launch complete");
}
```
以下是控制台输出。
这是程序控制台的输出。
```java
21:47:08.227 [executor-2] INFO com.iluwatar.async.method.invocation.App - Space rocket <test> launched successfully
@ -140,22 +140,21 @@ public static void main(String[] args) throws Exception {
21:47:08.618 [main] INFO com.iluwatar.async.method.invocation.App - Space rocket <50> launch complete
```
## 类图
# 类图
![alt text](../../async-method-invocation/etc/async-method-invocation.png "Async Method Invocation")
![alt text](../../../async-method-invocation/etc/async-method-invocation.png "Async Method Invocation")
## 适用场景
## 适用
在以下场景可以使用异步调用模式
在以下情况下使用异步方法调用模式
* 你有多有可以并行执行的独立任务
* 你需要提高一组串行任务的性能
* 你的处理能力有限、或者有长期运行的任务,调用者不应该等待任务所有任务运行结束
* 您有多个可以并行运行的独立任务
* 您需要提高一组顺序任务的性能
* 您的处理能力或长时间运行的任务数量有限,并且调用方不应等待任务执行完毕
## 现实示例
## 真实世界例子
* [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html)
* [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)
* [ExecutorService](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html)
* [Task-based Asynchronous Pattern](https://msdn.microsoft.com/en-us/library/hh873175.aspx)

View File

@ -4,33 +4,34 @@ title: Balking
folder: balking
permalink: /patterns/balking/
categories: Concurrency
language: zh
tags:
- Decoupling
---
## 含义
## 意图
阻止模式用于防止一个对象在不完整或不适当的状态下执行某段代码。
止步模式用于防止对象在不完整或不合适的状态下执行某些代码。
## 解释
真实世界的案
真实世界例
> 洗衣机里有一个用于启动衣物洗涤的启动按钮。当洗衣机没有启动时,该按钮可以正常按下生效,但如果洗衣机已经在洗衣服了,再按下按钮就不生效了
> 洗衣机中有一个开始按钮,用于启动衣物洗涤。当洗衣机处于非活动状态时,按钮将按预期工作,但是如果已经在洗涤,则按钮将不起任何作用
简而言之
通俗地说
> 使用阻止模式,只有当对象处于特定状态时,才会执行某段代码。
> 使用止步模式,仅当对象处于特定状态时才执行特定代码。
维基百科的解释
维基百科
> 阻止模式是一种软件设计模式,它只在对象处于特定状态时对其执行动作。例如,如果一个对象读取 ZIP 文件,当 ZIP 文件没有打开时,如果一个方法在该对象上调用一个获取方法,该对象就会对阻止这个请求
> 禁止模式是一种软件设计模式仅当对象处于特定状态时才对对象执行操作。例如一个对象读取zip压缩文件并在压缩文件没打开的时候调用get方法对象将在请求的时候”止步“
**程示例**
**程示例**
这个例子的实现中,`WashingMachine` 对象存在 2 种状态: `ENABLED``WASHING`。如果该对象处于 `ENABLED` 状态,则使用一个线程安全的方法可以其状态改变为 `WASHING`。在另一方面,如果它已经处于 `WASHING` 状态,而任何其他线程执行了 `wash()`,它不会执行该指令,而是什么都不做就返回。
此示例中,` WashingMachine`是一个具有两个状态的对象可以处于两种状态ENABLED和WASHING。 如果机器已启用则使用线程安全方法将状态更改为WASHING。 另一方面,如果已经进行了清洗并且任何其他线程执行`wash`,则它将不执行该操作,而是不执行任何操作而返回。
以下是 `WashingMachine` 类的相关代码
这里是`WashingMachine` 类相关的部分
```java
@Slf4j
@ -69,7 +70,7 @@ public class WashingMachine {
}
```
以下是 `WashingMachine` 使用的简单 `DelayProvider` 接口。
这里是一个`WashingMachine`所使用的`DelayProvider`简单接口。
```java
public interface DelayProvider {
@ -77,7 +78,7 @@ public interface DelayProvider {
}
```
现在我们介绍一下使用 `WashingMachine` 的应用
现在,我们使用`WashingMachine`介绍该应用程序
```java
public static void main(String... args) {
@ -96,7 +97,7 @@ public interface DelayProvider {
}
```
下是程序的控制台输出。
是程序的输出。
```
14:02:52.268 [pool-1-thread-2] INFO com.iluwatar.balking.WashingMachine - pool-1-thread-2: Actual machine state: ENABLED
@ -110,20 +111,21 @@ public interface DelayProvider {
## 类图
![alt text](../../balking/etc/balking.png "Balking")
![alt text](../../../balking/etc/balking.png "Balking")
## 适用场景
## 适用
在以下情况下可以使用阻止模式:
* 你想要在某个对象上调用一个动作,只有当该对象处于特定状态时才允许该调用。
* 对象一般只处于容易暂时阻止的状态,只不过该时间是未知的。
使用止步模式当
## 教学
* 您只想在对象处于特定状态时才对其调用操作
* 对象通常仅处于容易暂时停止但状态未知的状态
* [Guarded Suspension Pattern](https://java-design-patterns.com/patterns/guarded-suspension/)
* [Double Checked Locking Pattern](https://java-design-patterns.com/patterns/double-checked-locking/)
## 相关模式
## 引用
* [保护性暂挂模式](https://java-design-patterns.com/patterns/guarded-suspension/)
* [双重检查锁模式](https://java-design-patterns.com/patterns/double-checked-locking/)
## 鸣谢
* [Patterns in Java: A Catalog of Reusable Design Patterns Illustrated with UML, 2nd Edition, Volume 1](https://www.amazon.com/gp/product/0471227293/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0471227293&linkId=0e39a59ffaab93fb476036fecb637b99)

View File

@ -2,7 +2,7 @@
layout: pattern
title: Bridge
folder: bridge
permalink: /patterns/bridge/zh
permalink: /patterns/bridge/
categories: Structural
language: zh
tags:
@ -184,7 +184,7 @@ hammer.unwield();
## 类图
![alt text](../../bridge/etc/bridge.urm.png "Bridge class diagram")
![alt text](../../../bridge/etc/bridge.urm.png "Bridge class diagram")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Builder
folder: builder
permalink: /patterns/builder/zh
permalink: /patterns/builder/
categories: Creational
language: zh
tags:
@ -114,7 +114,7 @@ var mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.
## 类图
![alt text](../../builder/etc/builder.urm.png "Builder class diagram")
![alt text](../../../builder/etc/builder.urm.png "Builder class diagram")
## 适用性

View File

@ -4,36 +4,32 @@ title: Business Delegate
folder: business-delegate
permalink: /patterns/business-delegate/
categories: Structural
language: zh
tags:
- Decoupling
---
## 含义
## 意图
业务委托模式(译者:国内也有翻译成业务代表模式)在表现层和业务层之间增加了一个抽象层。通过使用该模式,我们获得了各层之间的松散耦合,并封装了关于如何定位、连接和与构成应用程序的业务对象进行交互的知识
业务委托模式在表示层和业务层之间添加了一个抽象层。 通过使用该模式,我们获得了各层之间的松散耦合,并封装了有关如何定位,连接到组成应用程序的业务对象以及与之交互的逻辑
## 解释
真实世界的案
真实世界例
> 一个手机应用程序承诺将现有的任何电影传输到你的手机上。它捕获了用户的搜索关键字内容,并将其传递给业务委托层。业务委托层选择最合适的视频流服务,并从该服务进行视频播放
> 手机应用程序承诺将现有的任何电影流式传输到您的手机。它捕获用户的搜索字符串,并将其传递给业务委托层。业务委托层选择最合适的视频流服务,然后从那里播放视频
简而言之
通俗的说
> 业务委托模式在表现层和业务层之间增加了一个抽象层。
> 业务委托模式在表示层和业务层之间添加了一个抽象层。
维基百科的解释
维基百科
> Business delegate is a Java EE design pattern. This pattern is directing to reduce the coupling
> in between business services and the connected presentation tier, and to hide the implementation
> details of services (including lookup and accessibility of EJB architecture). Business delegates
> acts as an adaptor to invoke business objects from the presentation tier.
>
> 业务委托模式是一种 Java EE 设计模式。这种模式旨在减少业务服务和所连接的表现层之间的耦合度,并隐藏服务的实现细节(包括 EJB 架构的查询和可访问性)。业务代表作为一个适配器,从表现层调用业务对象。
> 业务委托是一种Java EE设计模式。 该模式旨在减少业务服务与连接的表示层之间的耦合并隐藏服务的实现细节包括EJB体系结构的查找和可访问性。 业务代表充当适配器,以从表示层调用业务对象。
**程示例**
**程序示例**
首先,我们实现了一个视频流服务的抽象,和几个具体实现。
首先,我们有视频流服务的抽象类和一些它的实现。
```java
public interface VideoStreamingService {
@ -57,7 +53,7 @@ public class YouTubeService implements VideoStreamingService {
}
```
接下来,我们实现一个查询服务,用于决定使用哪个视频流服务。
然后我们有一个查找服务来决定我们使用哪个视频流服务。
```java
@Setter
@ -76,7 +72,7 @@ public class BusinessLookup {
}
```
业务委托层使用业务查询,将电影播放请求路由到合适的视频流服务。
业务委托类使用业务查找服务将电影播放请求路由到合适的视频流服务。
```java
@Setter
@ -108,7 +104,7 @@ public class MobileClient {
}
```
最后,我们展示一下这个示例完整的操作
最后我们展示完整示例
```java
public static void main(String[] args) {
@ -127,7 +123,7 @@ public class MobileClient {
}
```
以下是终端输出的内容
这是控制台的输出
```
21:15:33.790 [main] INFO com.iluwatar.business.delegate.NetflixService - NetflixService is now processing
@ -136,25 +132,25 @@ public class MobileClient {
## 类图
![alt text](../../business-delegate/etc/business-delegate.urm.png "Business Delegate")
![alt text](../../../business-delegate/etc/business-delegate.urm.png "Business Delegate")
## 相关模式
* [Service locator pattern](https://java-design-patterns.com/patterns/service-locator/)
* [服务定位器模式](https://java-design-patterns.com/patterns/service-locator/)
## 适用场景
## 适用
业务委托模式的适用场景:
使用业务委托模式当
* 你希望表现层和业务层之间是松耦合的。
* 你想要协调对多个业务服务的调用。
* 你想要对服务查询、服务调用进行封装。
* 你希望表示层和业务层之间的松散耦合
* 你想编排对多个业务服务的调用
* 你希望封装查找服务和服务调用
## 教程
* [Business Delegate Pattern at TutorialsPoint](https://www.tutorialspoint.com/design_pattern/business_delegate_pattern.htm)
## 引用
## 鸣谢
* [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=48d37c67fb3d845b802fa9b619ad8f31)
* [Core J2EE Patterns: Best Practices and Design Strategies](https://www.amazon.com/gp/product/0130648841/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=0130648841&linkId=a0100de2b28c71ede8db1757fb2b5947)

View File

@ -0,0 +1,235 @@
---
layout: pattern
title: Bytecode
folder: bytecode
permalink: /patterns/bytecode/
categories: Behavioral
language: zh
tags:
- Game programming
---
## 意图
允许编码行为作为虚拟机的指令。
## 解释
真实世界例子
> 一个团队正在开发一款新的巫师对战游戏。巫师的行为需要经过精心的调整和上百次的游玩测试。每次当游戏设计师想改变巫师行为时都让程序员去修改代码这是不妥的,所以巫师行为以数据驱动的虚拟机方式实现。
通俗地说
> 字节码模式支持由数据而不是代码驱动的行为。
[Gameprogrammingpatterns.com](https://gameprogrammingpatterns.com/bytecode.html) 中做了如下阐述:
> 指令集定义了可以执行的低级操作。一系列指令被编码为字节序列。虚拟机一次一条地执行这些指令,中间的值用栈处理。通过组合指令,可以定义复杂的高级行为。
**程序示例**
其中最重要的游戏对象是`巫师`类。
```java
@AllArgsConstructor
@Setter
@Getter
@Slf4j
public class Wizard {
private int health;
private int agility;
private int wisdom;
private int numberOfPlayedSounds;
private int numberOfSpawnedParticles;
public void playSound() {
LOGGER.info("Playing sound");
numberOfPlayedSounds++;
}
public void spawnParticles() {
LOGGER.info("Spawning particles");
numberOfSpawnedParticles++;
}
}
```
下面我们展示虚拟机可用的指令。每个指令对于如何操作栈中的数据都有自己的语义。例如,增加指令,其取得栈顶的两个元素并把结果压入栈中。
```java
@AllArgsConstructor
@Getter
public enum Instruction {
LITERAL(1), // e.g. "LITERAL 0", push 0 to stack
SET_HEALTH(2), // e.g. "SET_HEALTH", pop health and wizard number, call set health
SET_WISDOM(3), // e.g. "SET_WISDOM", pop wisdom and wizard number, call set wisdom
SET_AGILITY(4), // e.g. "SET_AGILITY", pop agility and wizard number, call set agility
PLAY_SOUND(5), // e.g. "PLAY_SOUND", pop value as wizard number, call play sound
SPAWN_PARTICLES(6), // e.g. "SPAWN_PARTICLES", pop value as wizard number, call spawn particles
GET_HEALTH(7), // e.g. "GET_HEALTH", pop value as wizard number, push wizard's health
GET_AGILITY(8), // e.g. "GET_AGILITY", pop value as wizard number, push wizard's agility
GET_WISDOM(9), // e.g. "GET_WISDOM", pop value as wizard number, push wizard's wisdom
ADD(10), // e.g. "ADD", pop 2 values, push their sum
DIVIDE(11); // e.g. "DIVIDE", pop 2 values, push their division
// ...
}
```
我们示例的核心是`虚拟机`类。 它将指令作为输入并执行它们以提供游戏对象行为。
```java
@Getter
@Slf4j
public class VirtualMachine {
private final Stack<Integer> stack = new Stack<>();
private final Wizard[] wizards = new Wizard[2];
public VirtualMachine() {
wizards[0] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),
0, 0);
wizards[1] = new Wizard(randomInt(3, 32), randomInt(3, 32), randomInt(3, 32),
0, 0);
}
public VirtualMachine(Wizard wizard1, Wizard wizard2) {
wizards[0] = wizard1;
wizards[1] = wizard2;
}
public void execute(int[] bytecode) {
for (var i = 0; i < bytecode.length; i++) {
Instruction instruction = Instruction.getInstruction(bytecode[i]);
switch (instruction) {
case LITERAL:
// Read the next byte from the bytecode.
int value = bytecode[++i];
// Push the next value to stack
stack.push(value);
break;
case SET_AGILITY:
var amount = stack.pop();
var wizard = stack.pop();
setAgility(wizard, amount);
break;
case SET_WISDOM:
amount = stack.pop();
wizard = stack.pop();
setWisdom(wizard, amount);
break;
case SET_HEALTH:
amount = stack.pop();
wizard = stack.pop();
setHealth(wizard, amount);
break;
case GET_HEALTH:
wizard = stack.pop();
stack.push(getHealth(wizard));
break;
case GET_AGILITY:
wizard = stack.pop();
stack.push(getAgility(wizard));
break;
case GET_WISDOM:
wizard = stack.pop();
stack.push(getWisdom(wizard));
break;
case ADD:
var a = stack.pop();
var b = stack.pop();
stack.push(a + b);
break;
case DIVIDE:
a = stack.pop();
b = stack.pop();
stack.push(b / a);
break;
case PLAY_SOUND:
wizard = stack.pop();
getWizards()[wizard].playSound();
break;
case SPAWN_PARTICLES:
wizard = stack.pop();
getWizards()[wizard].spawnParticles();
break;
default:
throw new IllegalArgumentException("Invalid instruction value");
}
LOGGER.info("Executed " + instruction.name() + ", Stack contains " + getStack());
}
}
public void setHealth(int wizard, int amount) {
wizards[wizard].setHealth(amount);
}
// other setters ->
// ...
}
```
现在我们可以展示使用虚拟机的完整示例。
```java
public static void main(String[] args) {
var vm = new VirtualMachine(
new Wizard(45, 7, 11, 0, 0),
new Wizard(36, 18, 8, 0, 0));
vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
vm.execute(InstructionConverterUtil.convertToByteCode("GET_HEALTH"));
vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
vm.execute(InstructionConverterUtil.convertToByteCode("GET_AGILITY"));
vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 0"));
vm.execute(InstructionConverterUtil.convertToByteCode("GET_WISDOM"));
vm.execute(InstructionConverterUtil.convertToByteCode("ADD"));
vm.execute(InstructionConverterUtil.convertToByteCode("LITERAL 2"));
vm.execute(InstructionConverterUtil.convertToByteCode("DIVIDE"));
vm.execute(InstructionConverterUtil.convertToByteCode("ADD"));
vm.execute(InstructionConverterUtil.convertToByteCode("SET_HEALTH"));
}
```
下面是控制台输出。
```
16:20:10.193 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0]
16:20:10.196 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_HEALTH, Stack contains [0, 45]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_AGILITY, Stack contains [0, 45, 7]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 7, 0]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed GET_WISDOM, Stack contains [0, 45, 7, 11]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 45, 18]
16:20:10.197 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed LITERAL, Stack contains [0, 45, 18, 2]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed DIVIDE, Stack contains [0, 45, 9]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed ADD, Stack contains [0, 54]
16:20:10.198 [main] INFO com.iluwatar.bytecode.VirtualMachine - Executed SET_HEALTH, Stack contains []
```
## 类图
![alt text](../../../bytecode/etc/bytecode.urm.png "Bytecode class diagram")
## 适用性
当您需要定义很多行为并且游戏的实现语言不合适时,请使用字节码模式,因为:
* 它的等级太低,使得编程变得乏味或容易出错。
* 由于编译时间慢或其他工具问题,迭代它需要很长时间。
* 它有太多的信任。 如果您想确保定义的行为不会破坏游戏,您需要将其与代码库的其余部分进行沙箱化。
## 相关模式
* [Interpreter](https://java-design-patterns.com/patterns/interpreter/)
## 鸣谢
* [Game programming patterns](http://gameprogrammingpatterns.com/bytecode.html)

View File

@ -2,7 +2,7 @@
layout: pattern
title: Caching
folder: caching
permalink: /patterns/caching/zh
permalink: /patterns/caching/
categories: Behavioral
language: zh
tags:
@ -14,7 +14,7 @@ tags:
为了避免昂贵的资源重新获取,方法是在资源使用后不立即释放资源。资源保留其身份,保留在某些快速访问的存储中,并被重新使用,以避免再次获取它们。
## 类图
![alt text](../../caching/etc/caching.png "Caching")
![alt text](../../../caching/etc/caching.png "Caching")
## 适用性
在以下情况下使用缓存模式

View File

@ -2,7 +2,7 @@
layout: pattern
title: Callback
folder: callback
permalink: /patterns/callback/zh
permalink: /patterns/callback/
categories: Idiom
language: zh
tags:
@ -69,7 +69,7 @@ public final class SimpleTask extends Task {
task.executeWith(() -> LOGGER.info("I'm done now."));
```
## 类图
![alt text](../../callback/etc/callback.png "Callback")
![alt text](../../../callback/etc/callback.png "Callback")
## 适用性
使用回调模式当

View File

@ -2,7 +2,7 @@
layout: pattern
title: Chain of responsibility
folder: chain
permalink: /patterns/chain/zh
permalink: /patterns/chain/
categories: Behavioral
language: zh
tags:
@ -139,7 +139,7 @@ king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc so
```
## 类图
![alt text](../../chain/etc/chain.urm.png "Chain of Responsibility class diagram")
![alt text](../../../chain/etc/chain.urm.png "Chain of Responsibility class diagram")
## 适用性
使用责任链模式当

View File

@ -4,39 +4,45 @@ title: Circuit Breaker
folder: circuit-breaker
permalink: /patterns/circuit-breaker/
categories: Behavioral
language: zh
tags:
- Performance
- Decoupling
- Cloud distributed
---
## 含义
## 意图
以这样的方式(译者:指断路器方式)处理昂贵的远程服务调用,可以防止单个服务/组件的故障导致整个应用程序崩溃,同时我们可以尽快地进行服务重连
以这样一种方式处理昂贵的远程服务调用,即单个服务/组件的故障不会导致整个应用程序宕机,我们可以尽快重新连接到服务
## 解释
现实世界案例
真实世界例子
> 设想一下,一个网络应用程序既有本地文件/图像,又有用于获取数据的远程服务。这些远程服务可能在某些时候是健康的、有反应的,也可能在某些时候由于各种原因而变得缓慢和无反应。因此,如果其中一个远程服务速度慢或不能成功响应,我们的应用程序将尝试使用多个线程/进程从远程服务中获取响应,很快所有的线程/进程都会挂起(也称为线程饥饿 thread starvation从而导致我们整个 Web 应用程序崩溃。我们应该能够检测到这种情况,并向用户显示一个适当的信息,以便用户可以探索应用程序的其他部分,而不受远程服务故障的影响。同时,其他正常工作的服务应该保持运作,不受这次故障的影响。
> 想象一个 Web 应用程序,它同时具有用于获取数据的本地文件/图像和远程服务。 这些远程服务有时可能健康且响应迅速,或者由于各种原因可能在某 个时间点变得缓慢和无响应。因此,如果其中一个远程服务缓慢或未成功响应,我们的应用程序将尝试使用多个线程/进程从远程服务获取响应,很快它们都会挂起(也称为 [线程饥饿][thread starvation](https://en.wikipedia.org/wiki/Starvation_(computer_science)))导致我们的整个 Web 应用程序崩溃。我们应该能够检测到这种情况并向用户显示适当的消息,以便他/她可以探索不受远程服务故障影响的应用程序的其他部分。 同时,其他正常工作的服务应保持正常运行,不受此故障的影响。
>
简而言之
通俗地说
> 断路器允许优雅地处理失败的远程服务。当我们的应用程序的所有部分都高度解耦时,这种方式的效果会很好,一个组件的失败并不会导致其他部分停止工作。
> 断路器允许优雅地处理失败的远程服务。当我们应用程序的所有部分彼此高度解耦时,它特别有用,一个组件的故障并不意味着其他部分将停止工作。
维基百科的解释
维基百科
> 断路器是现代软件开发中使用的一种设计模式。它用于检测故障,并封装了防止故障不断复发的逻辑,在维护期间,临时地处理外部系统故障或意外的系统问题
> 断路器是现代软件开发中使用的一种设计模式。 它用于检测故障并封装防止故障不断重复发生、维护期间、临时外部系统故障或意外系统困难的逻辑
## Programmatic Example
## 程序示例
那么,这一切是如何实现的呢?考虑到上面的例子,我们将在一个简单的例子中模拟这个功能。一个监控服务(译者:下图的 Monitoring Service模拟了网络应用进行本地和远程调用。
So, how does this all come together? With the above example in mind we will imitate the
functionality in a simple example. A monitoring service mimics the web app and makes both local and
remote calls.
该服务架构如下:
那么,这一切是如何结合在一起的呢? 记住上面的例子,我们将在一个简单的例子中模仿这个功能。 监控服务模仿 Web 应用程序并进行本地和远程调用。
![alt text](../../circuit-breaker/etc/ServiceDiagram.png "Service Diagram")
服务架构如下:
终端用户(译者:上图的 End User应用的代码如下
![alt text](../../../circuit-breaker/etc/ServiceDiagram.png "Service Diagram")
在代码方面,最终用户应用程序是:
```java
@Slf4j
@ -61,44 +67,44 @@ public class App {
var quickServiceCircuitBreaker = new DefaultCircuitBreaker(quickService, 3000, 2,
2000 * 1000 * 1000);
//Create an object of monitoring service which makes both local and remote calls
// 创建一个可以进行本地和远程调用的监控服务对象
var monitoringService = new MonitoringService(delayedServiceCircuitBreaker,
quickServiceCircuitBreaker);
//Fetch response from local resource
// 获取本地资源
LOGGER.info(monitoringService.localResourceResponse());
//Fetch response from delayed service 2 times, to meet the failure threshold
// 从延迟服务中获取响应 2 次,以满足失败阈值
LOGGER.info(monitoringService.delayedServiceResponse());
LOGGER.info(monitoringService.delayedServiceResponse());
//Fetch current state of delayed service circuit breaker after crossing failure threshold limit
//which is OPEN now
// 在超过故障阈值限制后获取延迟服务断路器的当前状态
// 现在是打开状态
LOGGER.info(delayedServiceCircuitBreaker.getState());
//Meanwhile, the delayed service is down, fetch response from the healthy quick service
// 同时,延迟服务宕机,从健康快速服务获取响应
LOGGER.info(monitoringService.quickServiceResponse());
LOGGER.info(quickServiceCircuitBreaker.getState());
//Wait for the delayed service to become responsive
// 等待延迟的服务响应
try {
LOGGER.info("Waiting for delayed service to become responsive");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Check the state of delayed circuit breaker, should be HALF_OPEN
// 检查延时断路器的状态,应该是HALF_OPEN
LOGGER.info(delayedServiceCircuitBreaker.getState());
//Fetch response from delayed service, which should be healthy by now
// 从延迟服务中获取响应,现在应该是健康的
LOGGER.info(monitoringService.delayedServiceResponse());
//As successful response is fetched, it should be CLOSED again.
// 获取成功响应后,它的状态应该是关闭。
LOGGER.info(delayedServiceCircuitBreaker.getState());
}
}
```
监控服务代码(译者:上图的 monitoring service
监控服务类:
```java
public class MonitoringService {
@ -112,7 +118,7 @@ public class MonitoringService {
this.quickService = quickService;
}
//Assumption: Local service won't fail, no need to wrap it in a circuit breaker logic
// 假设:本地服务不会失败,无需将其包装在断路器逻辑中
public String localResourceResponse() {
return "Local Service is working";
}
@ -144,7 +150,7 @@ public class MonitoringService {
}
}
```
可以看出,它直接进行了获取本地资源的调用,但它把对远程(昂贵的)服务的调用包装在一个断路器对象中,这样可以防止出现如下故障
可以看出,它直接调用获取本地资源,但它将对远程(昂贵)服务的调用包装在断路器对象中,防止故障如下
```java
public class DefaultCircuitBreaker implements CircuitBreaker {
@ -171,11 +177,11 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
DefaultCircuitBreaker(RemoteService serviceToCall, long timeout, int failureThreshold,
long retryTimePeriod) {
this.service = serviceToCall;
// We start in a closed state hoping that everything is fine
// 我们从关闭状态开始希望一切都是正常的
this.state = State.CLOSED;
this.failureThreshold = failureThreshold;
// Timeout for the API request.
// Used to break the calls made to remote resource if it exceeds the limit
// API的超时时间.
// 用于在超过限制时中断对远程资源的调用
this.timeout = timeout;
this.retryTimePeriod = retryTimePeriod;
//An absurd amount of time in future which basically indicates the last failure never happened
@ -183,7 +189,7 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
this.failureCount = 0;
}
// Reset everything to defaults
// 重置所有
@Override
public void recordSuccess() {
this.failureCount = 0;
@ -199,18 +205,18 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
this.lastFailureResponse = response;
}
// Evaluate the current state based on failureThreshold, failureCount and lastFailureTime.
// 根据 failureThreshold、failureCount 和 lastFailureTime 评估当前状态。
protected void evaluateState() {
if (failureCount >= failureThreshold) { //Then something is wrong with remote service
if ((System.nanoTime() - lastFailureTime) > retryTimePeriod) {
//We have waited long enough and should try checking if service is up
// 我们已经等得够久了,应该尝试检查服务是否已启动
state = State.HALF_OPEN;
} else {
//Service would still probably be down
// 服务可能仍会出现故障
state = State.OPEN;
}
} else {
//Everything is working fine
// 一切正常
state = State.CLOSED;
}
}
@ -253,16 +259,15 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
public String attemptRequest() throws RemoteServiceException {
evaluateState();
if (state == State.OPEN) {
// return cached response if the circuit is in OPEN state
// 如果电路处于打开状态,则返回缓存的响应
return this.lastFailureResponse;
} else {
// Make the API request if the circuit is not OPEN
// 如果电路未打开,则发出 API 请求
try {
//In a real application, this would be run in a thread and the timeout
//parameter of the circuit breaker would be utilized to know if service
//is working. Here, we simulate that based on server response itself
//在实际应用程序中,这将在线程中运行,并且将利用断路器的超时参数来了解服务
// 是否正在工作。 在这里,我们根据服务器响应本身模拟
var response = service.call();
// Yay!! the API responded fine. Let's reset everything.
// api 响应正常,重置所有。
recordSuccess();
return response;
} catch (RemoteServiceException ex) {
@ -274,39 +279,39 @@ public class DefaultCircuitBreaker implements CircuitBreaker {
}
```
上述模式是如何防止失败的呢?让我们通过它所实现的这个有限状态机来了解。
上述模式如何防止失败? 让我们通过它实现的这个有限状态机来理解。
![alt text](../../circuit-breaker/etc/StateDiagram.png "State Diagram")
![alt text](../../../circuit-breaker/etc/StateDiagram.png "State Diagram")
- 我们`timeout`(超时)、 `failureThreshold` (失败阈值)、`retryTimePeriod`(重试时间周期) 参数初始化断路器对象 ,用于确定 API 的适应性。
- 最初,断路器处于 `closed` 关闭状态,没有发生对 API 的远程调用。
- 每次调用成功,我们就把状态重置为开始时的样子
- 如果失败的次数超过了一定的阈值(`failureThreshold`),断路器就会进入 `open` 开启状态,它的作用就像一个开启的电路,阻止远程服务的调用,从而节省资源。
- 一旦我们超过重试时间周期(`retryTimePeriod`),断路器就会转到 `half-open` 半启用状态,并再次调用远程服务,检查服务是否正常,以便我们可以提供最新的响应内容。如果远程服务调用失败会使断路器回到 `open` 状态,并在重试超时后进行另一次尝试;如果远程服务调用成功则使断路器进入 `closed` 状态,这样一切又开始正常工作。
- 我们使用某些参数初始化断路器对象:`timeout``failureThreshold``retryTimePeriod`,这有助于确定 API 的弹性。
- 最初,我们处于“关闭”状态,没有发生对 API 的远程调用。
- 每次调用成功时,我们都会将状态重置为开始时的状态
- 如果失败次数超过某个阈值我们将进入“open”状态这就像开路一样阻止远程服务调用从而节省资源。 (这里,我们从 API 返回名为 ```stale response``` 的响应)
- 一旦超过重试超时时间,我们就会进入“半开”状态并再次调用远程服务以检查服务是否正常工作,以便我们可以提供新鲜内容。 失败将其设置回“打开”状态,并在重试超时时间后进行另一次尝试,而成功将其设置为“关闭”状态,以便一切重新开始正常工作。
## 类图
![alt text](../../circuit-breaker/etc/circuit-breaker.urm.png "Circuit Breaker class diagram")
![alt text](../../../circuit-breaker/etc/circuit-breaker.urm.png "Circuit Breaker class diagram")
## 适用场景
## 适用
在以下场景下,可以使用断路器模式:
在以下情况下使用断路器模式
- 构建一个高可用的应用程序,某些些服务的失败不会导致整个应用程序的崩溃
- 构建一个持续运行(长期在线)的应用程序,以便其组件可以在不完全关闭的情况下进行升级。
- 构建一个容错应用程序,其中某些服务的故障不应导致整个应用程序宕机
- 构建一个持续运行(永远在线)的应用程序,这样它的组件就可以在不完全关闭的情况下升级。
## 相关模式
- [Retry Pattern](https://github.com/iluwatar/java-design-patterns/tree/master/retry)
## 现实案例
## 真实世界例子
* [Spring Circuit Breaker module](https://spring.io/guides/gs/circuit-breaker)
* [Netflix Hystrix API](https://github.com/Netflix/Hystrix)
## 引用
## 鸣谢
* [Understanding Circuit Breaker Pattern](https://itnext.io/understand-circuitbreaker-design-pattern-with-simple-practical-example-92a752615b42)
* [Martin Fowler on Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html)
* [Fault tolerance in a high volume, distributed system](https://medium.com/netflix-techblog/fault-tolerance-in-a-high-volume-distributed-system-91ab4faae74a)
* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)
* [Circuit Breaker pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)

View File

@ -0,0 +1,134 @@
---
layout: pattern
title: Static Content Hosting
folder: cloud-static-content-hosting
permalink: /patterns/cloud-static-content-hosting/
categories: Cloud
language: zh
tags:
- Cloud distributed
---
## 意图
将静态内容部署到基于云的存储服务,该服务可以将它们直接交付给客户端。 这可以减少对昂贵计算实例的需求。
## 解释
真实世界例子
> 全球性的营销网站(静态内容)需要快速的部署以开始吸引潜在的客户。为了将托管费用和维护成本降至最低,使用云托管存储服务和内容交付网络。
通俗地说
> 静态内容托管模式利用云原生存储服务来存储内容和全球内容交付网络,将其缓存在世界各地的多个数据中心。 在静态网站上,单个网页包含静态内容。 它们还可能包含客户端脚本,例如 Javascript。相比之下动态网站依赖于服务器端处理包括服务器端脚本如 PHP、JSP 或 ASP.NET。
维基百科说
> 与由 Web 应用程序生成的动态网页相反,静态网页(有时称为平面网页或固定网页)是完全按照存储的方式传送到用户的网页浏览器的网页。静态网页适用于从不或很少需要更新的内容,尽管现代
> Web 模板系统正在改变这一点。可以将大量静态页面作为文件进行维护,没有自动化工具(例如静态站点生成器)是不切实际的。
**示例**
![alt text](../../../cloud-static-content-hosting/etc/static-content-hosting.png "Static Content Hosting")
在这个例子中我们使用AWS S3创建一个静态网站并利用 AWS Cloudfront 在全球范围内分发内容。
1. 首先你需要一个AWS账户你可以在这个创建一个免费的[AWS Free Tier](https://aws.amazon.com/free/free-tier/)
2. 登陆 [AWS控制台](https://console.aws.amazon.com/console/home?nc2=h_ct&src=header-signin)
3. 进入身份和接入管理服务 (IAM) .
4. 创建一个仅具有此应用程序必要权限的IAM用户。
* 点击 `用户`
* 点击 `添加用户`. 选择你想要的 `用户名` `接入类型`应该是 `编程式接入`. 点击 `下一步: 权限`.
* 选择 `直接附加已存在的策略`. 选择 `AmazonS3FullAccess``CloudFrontFullAccess`. Click `下一步: 标签`.
* 没有需要的标签, 所以直接点击 `下一步: 回顾`.
* 检查呈现的信息,没问题的话点击`创建用户`
* 完成这个示例所需要的`访问秘钥Id``访问秘钥密码`将会呈现在你面前,请妥善保管。
* 点击 `关闭`.
5. [安装AWS 命令行工具 (AWS CLI)](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html) 来获得编程式访问AWS云。
6. 使用`aws configure`命令来配置AWS CLI [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-config)
7. 为web站点创建AWS S3 bucket。 注意S3 bucket名字必须要在全球范围内唯一。
* 语法是 `aws s3 mb <bucket name>` [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-buckets-creating)
* 比如 `aws s3 mb s3://my-static-website-jh34jsjmg`
* 使用列出现有存储桶的命令`aws s3 ls`验证存储桶是否已成功创建
8. 使用命令`aws s3 website`来配置bucket作为web站点。 [说明书](https://docs.aws.amazon.com/cli/latest/reference/s3/website.html).
* 比如`aws s3 website s3://my-static-website-jh34jsjmg --index-document index.html --error-document error.html`
9. 上传内容到bucket中。
* 首先创建内容,至少包含`index.html``error.html`文档。
* 上传内容到你的bucket中。 [说明书](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-copy)
* 比如`aws s3 cp index.html s3://my-static-website-jh34jsjmg` and `aws s3 cp error.html s3://my-static-website-jh34jsjmg`
10. 然后我们需要设置bucket的策略以允许读取访问。
* 使用以下内容创建`policy.json`注意需要将bucket名称替换为自己的
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-static-website-jh34jsjmg/*"
}
]
}
```
* 根据这些设置桶策略[说明书](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-bucket-policy.html)
* 比如 `aws s3api put-bucket-policy --bucket my-static-website-jh34jsjmg --policy file://policy.json`
11. 使用浏览器测试web站点。
* web站点的URL格式是 `http://<bucket-name>.s3-website-<region-name>.amazonaws.com`
* 比如 这个站点创建在 `eu-west-1` 区域 ,名字是 `my-static-website-jh34jsjmg` 所以它可以通过 `http://my-static-website-jh34jsjmg.s3-website-eu-west-1.amazonaws.com`来访问。
12. 为web站点创建CloudFormation 分发。
* 语法文档在这里 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-distribution.html)
* 比如最简单的方式是使用命令l `aws cloudfront create-distribution --origin-domain-name my-static-website-jh34jsjmg.s3.amazonaws.com --default-root-object index.html`
* 也支持JSON格式的配置 比如使用 `--distribution-config file://dist-config.json` 来传递分发的配置文件参数
* 命令的舒勇将显示准确的分配配置项,包括包括可用于测试的生成的 CloudFront 域名,例如 `d2k3xwnaqa8nqx.cloudfront.net`
* CloudFormation 分发部署需要一些时间,但一旦完成,您的网站就会从全球各地的数据中心提供服务!
13. 就是这样! 您已经实现了一个静态网站,其内容分发网络以闪电般的速度在世界各地提供服务。
* 要更新网站,您需要更新 S3 存储桶中的对象并使 CloudFront 分配中的对象无效
* 要从 AWS CLI 执行此操作,请参阅 [this reference](https://docs.aws.amazon.com/cli/latest/reference/cloudfront/create-invalidation.html)
* 您可能想要做的进一步开发是通过 https 提供内容并为您的站点添加域名
## 适用性
当您想要执行以下操作时,请使用静态内容托管模式:
* 最小化包含一些静态资源的网站和应用程序的托管成本。
* 使用静态内容构建全球可用的网站
* 监控网站流量、带宽使用、成本等。
## 典型用例
* 具有全球影响力的网站
* 静态网站生成器生成的内容
* 没有动态内容要求的网站
## 真实世界例子
* [Java Design Patterns web site](https://java-design-patterns.com)
## 鸣谢
* [Static Content Hosting pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/static-content-hosting)

View File

@ -4,6 +4,7 @@ title: Collection Pipeline
folder: collection-pipeline
permalink: /patterns/collection-pipeline/
categories: Functional
language: zh
tags:
- Reactive
---
@ -13,7 +14,7 @@ tags:
在函数式编程中,可以通过一系列较小的模块化函数或操作来编排复杂的操作。这一系列函数被称为函数组合。当一个数据集合流经一个函数组合时,它就成为一个集合管道。函数组合和集合管道是函数式编程中经常使用的两种设计模式。
## 类图
![alt text](../../collection-pipeline/etc/collection-pipeline.png "Collection Pipeline")
![alt text](../../../collection-pipeline/etc/collection-pipeline.png "Collection Pipeline")
## 适用场景
在以下场景适用集合管道模式:

View File

@ -2,7 +2,7 @@
layout: pattern
title: Command
folder: command
permalink: /patterns/command/zh
permalink: /patterns/command/
categories: Behavioral
language: zh
tags:
@ -222,7 +222,7 @@ goblin.printStatus();
```
## 类图
![alt text](../../command/etc/command.png "Command")
![alt text](../../../command/etc/command.png "Command")
## 适用性
使用命令模式当你想

View File

@ -4,6 +4,7 @@ title: Composite Entity
folder: composite-entity
permalink: /patterns/composite-entity/
categories: Structural
language: zh
tags:
- Enterprise Integration Pattern
---
@ -109,7 +110,7 @@ Arrays.stream(console.getData()).forEach(LOGGER::info);
## 类图
![alt text](../../composite-entity/etc/composite_entity.urm.png "Composite Entity Pattern")
![alt text](../../../composite-entity/etc/composite_entity.urm.png "Composite Entity Pattern")
## 适用场景

View File

@ -2,7 +2,7 @@
layout: pattern
title: Composite
folder: composite
permalink: /patterns/composite/zh
permalink: /patterns/composite/
categories: Structural
language: zh
tags:
@ -154,7 +154,7 @@ elfMessage.print(); // Much wind pours from your mouth.
## 类图
![alt text](../../composite/etc/composite.urm.png "Composite class diagram")
![alt text](../../../composite/etc/composite.urm.png "Composite class diagram")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Converter
folder: converter
permalink: /patterns/converter/zh
permalink: /patterns/converter/
categories: Creational
language: zh
tags:
@ -86,7 +86,7 @@ var user = userConverter.convertFromDto(dtoUser);
## 类图
![alt text](../../converter/etc/converter.png "Converter Pattern")
![alt text](../../../converter/etc/converter.png "Converter Pattern")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Data Access Object
folder: dao
permalink: /patterns/dao/zh
permalink: /patterns/dao/
categories: Architectural
language: zh
tags:
@ -149,7 +149,7 @@ customerDao.getAllCustomers(): java.util.stream.ReferencePipeline$Head@6ec8211c
## 类图
![alt text](../../dao/etc/dao.png "Data Access Object")
![alt text](../../../dao/etc/dao.png "Data Access Object")
## 适用性

View File

@ -3,8 +3,8 @@ layout: pattern
title: Data Bus
folder: data-bus
permalink: /patterns/data-bus/
categories: Architectural
language: zh
tags:
- Decoupling
---
@ -14,7 +14,7 @@ tags:
数据总线模式(译者:实际上,就是 Event-Bus 消息总线模式)允许在一个应用程序的组件之间收发消息/事件,而不需要这些组件相互感知,它们只需要知道所发送/接收的消息/事件的类型即可。
## 类图
![data bus pattern uml diagram](../../data-bus/etc/data-bus.urm.png "Data Bus pattern")
![data bus pattern uml diagram](../../../data-bus/etc/data-bus.urm.png "Data Bus pattern")
## 适用场景
可以在以下场景使用数据总线模式:

View File

@ -4,6 +4,7 @@ title: Data Mapper
folder: data-mapper
permalink: /patterns/data-mapper/
categories: Architectural
language: zh
tags:
- Decoupling
---
@ -12,7 +13,7 @@ tags:
一个用于在持久化对象和数据库之间传输数据的映射器,同时保持它们之间和映射器本身的独立性。
## 类图
![alt text](../../data-mapper/etc/data-mapper.png "Data Mapper")
![alt text](../../../data-mapper/etc/data-mapper.png "Data Mapper")
## 适用场景
数据映射器适用于以下场景:

View File

@ -2,7 +2,7 @@
layout: pattern
title: Data Transfer Object
folder: data-transfer-object
permalink: /patterns/data-transfer-object/zh
permalink: /patterns/data-transfer-object/
categories: Architectural
language: zh
tags:
@ -94,7 +94,7 @@ public class CustomerResource {
## 类图
![alt text](../../data-transfer-object/etc/data-transfer-object.urm.png "data-transfer-object")
![alt text](../../../data-transfer-object/etc/data-transfer-object.urm.png "data-transfer-object")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Decorator
folder: decorator
permalink: /patterns/decorator/zh
permalink: /patterns/decorator/
categories: Structural
language: zh
tags:
@ -106,7 +106,7 @@ clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!
```
## 类图
![alt text](../../decorator/etc/decorator.urm.png "Decorator pattern class diagram")
![alt text](../../../decorator/etc/decorator.urm.png "Decorator pattern class diagram")
## 适用性
使用装饰者

View File

@ -2,7 +2,7 @@
layout: pattern
title: Delegation
folder: delegation
permalink: /patterns/delegation/zh
permalink: /patterns/delegation/
categories: Structural
language: zh
tags:
@ -16,7 +16,7 @@ tags:
它是一种让对象将某种行为向外部表达,但实际上将实现该行为的责任委托给关联对象的技术。
## 类图
![alt text](../../delegation/etc/delegation.png "Delegate")
![alt text](../../../delegation/etc/delegation.png "Delegate")
## 适用性
使用委托模式以实现以下目的

View File

@ -2,7 +2,7 @@
layout: pattern
title: Dependency Injection
folder: dependency-injection
permalink: /patterns/dependency-injection/zh
permalink: /patterns/dependency-injection/
categories: Creational
language: zh
tags:
@ -84,7 +84,7 @@ public class AdvancedWizard implements Wizard {
## 类图
![alt text](../../dependency-injection/etc/dependency-injection.png "Dependency Injection")
![alt text](../../../dependency-injection/etc/dependency-injection.png "Dependency Injection")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Dirty Flag
folder: dirty-flag
permalink: /patterns/dirty-flag/zh
permalink: /patterns/dirty-flag/
categories: Behavioral
language: zh
tags:
@ -17,7 +17,7 @@ tags:
避免昂贵资源的重新获取。资源保留其身份,保留在某些快速访问的存储中,并被重新使用以避免再次获取它们。
## 类图
![alt text](../../dirty-flag/etc/dirty-flag.png "Dirty Flag")
![alt text](../../../dirty-flag/etc/dirty-flag.png "Dirty Flag")
## 适用性
在以下情况下使用脏标志模式

View File

@ -4,6 +4,7 @@ title: Double Checked Locking
folder: double-checked-locking
permalink: /patterns/double-checked-locking/
categories: Idiom
language: zh
tags:
- Performance
---
@ -12,7 +13,7 @@ tags:
通过先测试锁定标准("锁提示")而不实际获取锁的方式来减少获取锁的开销。只有当锁定标准检查表明需要锁定时,才进行实际的锁定逻辑。
## 类图
![alt text](../../double-checked-locking/etc/double_checked_locking_1.png "Double Checked Locking")
![alt text](../../../double-checked-locking/etc/double_checked_locking_1.png "Double Checked Locking")
## 适用场景
在以下场景适合使用双重锁检查模式:

View File

@ -2,7 +2,7 @@
layout: pattern
title: Facade
folder: facade
permalink: /patterns/facade/zh
permalink: /patterns/facade/
categories: Structural
language: zh
tags:
@ -189,7 +189,7 @@ facade.endDay();
```
## 类图
![alt text](../../facade/etc/facade.urm.png "Facade pattern class diagram")
![alt text](../../../facade/etc/facade.urm.png "Facade pattern class diagram")
## 适用性
使用外观模式当

View File

@ -4,6 +4,7 @@ title: Factory Kit
folder: factory-kit
permalink: /patterns/factory-kit/
categories: Creational
language: zh
tags:
- Extensibility
---
@ -12,7 +13,7 @@ tags:
使用分离的构建器和工厂接口来定义一个不可变内容的工厂。
## 类图
![alt text](../../factory-kit/etc/factory-kit.png "Factory Kit")
![alt text](../../../factory-kit/etc/factory-kit.png "Factory Kit")
## 适用场景
工厂套件模式适用于与以下场景:

View File

@ -2,7 +2,7 @@
layout: pattern
title: Factory Method
folder: factory-method
permalink: /patterns/factory-method/zh
permalink: /patterns/factory-method/
categories: Creational
language: zh
tags:
@ -63,7 +63,7 @@ blacksmith.manufactureWeapon(WeaponType.AXE);
```
## 类图
![alt text](../../factory-method/etc/factory-method.urm.png "Factory Method pattern class diagram")
![alt text](../../../factory-method/etc/factory-method.urm.png "Factory Method pattern class diagram")
## 适用性
使用工厂方法模式当

View File

@ -4,6 +4,7 @@ title: Factory
folder: factory
permalink: /patterns/factory/
categories: Creational
language: zh
tags:
- Gang of Four
---
@ -108,7 +109,7 @@ This is Ferrari.
## 类图
![alt text](../../factory/etc/factory.urm.png "Factory pattern class diagram")
![alt text](../../../factory/etc/factory.urm.png "Factory pattern class diagram")
## 适用场景

View File

@ -2,7 +2,7 @@
layout: pattern
title: Interpreter
folder: interpreter
permalink: /patterns/interpreter/zh
permalink: /patterns/interpreter/
categories: Behavioral
language: zh
tags:
@ -13,7 +13,7 @@ tags:
给定一种语言,请定义其语法的表示形式,以及使用该表示形式来解释该语言中的句子的解释器。
## 类图
![alt text](../../interpreter/etc/interpreter_1.png "Interpreter")
![alt text](../../../interpreter/etc/interpreter_1.png "Interpreter")
## 适用性
有一种要解释的语言时,请使用解释器模式,并且可以将语言中的语句表示为抽象语法树。解释器模式在以下情况下效果最佳

View File

@ -2,7 +2,7 @@
layout: pattern
title: Iterator
folder: iterator
permalink: /patterns/iterator/zh
permalink: /patterns/iterator/
categories: Behavioral
language: zh
tags:
@ -115,7 +115,7 @@ while (itemIterator.hasNext()) {
```
## 类图
![alt text](../../iterator/etc/iterator_1.png "Iterator")
![alt text](../../../iterator/etc/iterator_1.png "Iterator")
## 适用性
以下情况使用迭代器模式

View File

@ -2,7 +2,7 @@
layout: pattern
title: Observer
folder: observer
permalink: /patterns/observer/zh
permalink: /patterns/observer/
categories: Behavioral
language: zh
tags:
@ -129,7 +129,7 @@ public class Weather {
```
## Class diagram
![alt text](../../observer/etc/observer.png "Observer")
![alt text](../../../observer/etc/observer.png "Observer")
## 应用
在下面任何一种情况下都可以使用观察者模式

View File

@ -2,7 +2,7 @@
layout: pattern
title: Private Class Data
folder: private-class-data
permalink: /patterns/private-class-data/zh
permalink: /patterns/private-class-data/
categories: Idiom
language: zh
tags:
@ -120,7 +120,7 @@ immutableStew.mix(); // Mixing the immutable stew we find: 2 potatoes, 4 carrot
## 类图
![alt text](../../private-class-data/etc/private-class-data.png "Private Class Data")
![alt text](../../../private-class-data/etc/private-class-data.png "Private Class Data")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Producer Consumer
folder: producer-consumer
permalink: /patterns/producer-consumer/zh
permalink: /patterns/producer-consumer/
categories: Concurrency
language: zh
tags:
@ -13,7 +13,7 @@ tags:
生产者消费者设计模式是一种经典的并发模式,通过将工作与执行工作任务分开来减少生产者与消费者之间的耦合。
## 类图
![alt text](../../producer-consumer/etc/producer-consumer.png "Producer Consumer")
![alt text](../../../producer-consumer/etc/producer-consumer.png "Producer Consumer")
## 适用性
在以下情况下使用生产者消费者

View File

@ -2,7 +2,7 @@
layout: pattern
title: Proxy
folder: proxy
permalink: /patterns/proxy/zh
permalink: /patterns/proxy/
categories: Structural
language: zh
tags:
@ -123,7 +123,7 @@ Brown wizard is not allowed to enter!
## 类图
![alt text](../../proxy/etc/proxy.urm.png "Proxy pattern class diagram")
![alt text](../../../proxy/etc/proxy.urm.png "Proxy pattern class diagram")
## 适用性

View File

@ -4,6 +4,7 @@ title: Sharding
folder: sharding
permalink: /patterns/sharding/
categories: Behavioral
language: zh
tags:
- Performance
- Cloud distributed
@ -15,7 +16,7 @@ tags:
一个分片本身就是一个数据存储(它可以包含许多不同类型的实体的数据),运行在作为存储节点的服务器上。
## 类图
![alt text](../../sharding/etc/sharding.urm.png "Sharding pattern class diagram")
![alt text](../../../sharding/etc/sharding.urm.png "Sharding pattern class diagram")
## 适用场景
这种设计模式提供了一下的好处:

View File

@ -2,7 +2,7 @@
layout: pattern
title: State
folder: state
permalink: /patterns/state/zh
permalink: /patterns/state/
categories: Behavioral
language: zh
tags:
@ -135,7 +135,7 @@ public class Mammoth {
```
## 类图
![alt text](../../state/etc/state_urm.png "State")
![alt text](../../../state/etc/state_urm.png "State")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Strategy
folder: strategy
permalink: /patterns/strategy/zh
permalink: /patterns/strategy/
categories: Behavioral
language: zh
tags:
@ -112,7 +112,7 @@ public class DragonSlayer {
```
## 类图
![alt text](../../strategy/etc/strategy_1.png "Strategy")
![alt text](../../../strategy/etc/strategy_urm.png "Strategy")
## 应用
使用策略模式当

View File

@ -2,7 +2,7 @@
layout: pattern
title: Template method
folder: template-method
permalink: /patterns/template-method/zh
permalink: /patterns/template-method/
categories: Behavioral
language: zh
tags:
@ -119,7 +119,7 @@ public class HalflingThief {
```
## 类图
![alt text](../../template-method/etc/template_method_urm.png "Template Method")
![alt text](../../../template-method/etc/template_method_urm.png "Template Method")
## 适用性

View File

@ -2,13 +2,13 @@
layout: pattern
title: Version Number
folder: versionnumber
permalink: /patterns/versionnumber/zh
permalink: /patterns/versionnumber/
description: Entity versioning with version number
language: zh
categories:
- Concurrency
language: zh
tags:
- Data access
- Microservices
@ -135,7 +135,7 @@ Exception: Tried to update stale version 0 while actual version is 1
## 类图
![alt text](../../version-number/etc/version-number.urm.png "Version Number pattern class diagram")
![alt text](../../../version-number/etc/version-number.urm.png "Version Number pattern class diagram")
## 适用性

View File

@ -2,7 +2,7 @@
layout: pattern
title: Visitor
folder: visitor
permalink: /patterns/visitor/zh
permalink: /patterns/visitor/
categories: Behavioral
language: zh
tags:
@ -201,7 +201,7 @@ Good to see you commander
## Class diagram
![alt text](../../visitor/etc/visitor_1.png "Visitor")
![alt text](../../../visitor/etc/visitor_1.png "Visitor")
## 适用性