Compare commits

...

22 Commits

Author SHA1 Message Date
allcontributors[bot]
d42bcab9fc docs: update .all-contributorsrc [skip ci] 2020-11-07 12:34:36 +00:00
allcontributors[bot]
77b2ff2150 docs: update README.md [skip ci] 2020-11-07 12:34:35 +00:00
Ilkka Seppälä
cff072d1ca Merge pull request #1593 from iluwatar/all-contributors/add-dsibilio
docs: add dsibilio as a contributor
2020-11-07 14:34:08 +02:00
allcontributors[bot]
80ba0407db docs: update .all-contributorsrc [skip ci] 2020-11-07 12:33:11 +00:00
allcontributors[bot]
6a09b909f2 docs: update README.md [skip ci] 2020-11-07 12:33:10 +00:00
Ilkka Seppälä
53ccc0e7e6 Merge pull request #1548 from dsibilio/patch-1
Add missing word to README.md
2020-11-07 14:31:26 +02:00
Ilkka Seppälä
a7a8e23b01 Merge pull request #1591 from iluwatar/all-contributors/add-Ascenio
docs: add Ascenio as a contributor
2020-11-07 09:49:20 +02:00
allcontributors[bot]
2783251d00 docs: update .all-contributorsrc [skip ci] 2020-11-07 07:47:42 +00:00
allcontributors[bot]
ac432968ae docs: update README.md [skip ci] 2020-11-07 07:47:41 +00:00
Ilkka Seppälä
f006782805 Merge pull request #1529 from mookkiah/issue_1500
issue 1500 - using JUnit 5 and resolved a build issue
2020-10-17 18:02:56 +03:00
Ilkka Seppälä
1f4a412e70 Merge pull request #1535 from ohbus/master
Cache SonarCloud packages
2020-10-10 18:51:00 +03:00
Domenico Sibilio
36d0a3718c Update README.md
Missing word in sentence.
2020-10-06 18:24:47 +02:00
Ilkka Seppälä
195a735814 #508 fix SpaceStationMir logging 2020-10-04 14:50:48 +03:00
Ilkka Seppälä
633d45aa67 Fix typo 2020-10-04 14:33:01 +03:00
Ilkka Seppälä
adc267e48e Merge pull request #1526 from xiaod-dev/translation-zh
Translation zh
2020-10-04 14:26:39 +03:00
Ilkka Seppälä
cc8d209c22 Merge pull request #1545 from iluwatar/all-contributors/add-ChFlick
docs: add ChFlick as a contributor
2020-10-04 14:24:48 +03:00
Subhrodip Mohanta
a3753807ae add Caching of SonarCloud packages 2020-10-01 22:23:43 +05:30
Subhrodip Mohanta
64266d63fd Merge pull request #1 from iluwatar/master
Update README.md
2020-10-01 22:18:53 +05:30
Mahendran Mookkiah
ad435dd2fd issue 1500 - using Junit 5 and resolved a build issue 2020-09-27 09:26:19 -04:00
Mike
dac8e659ce add facade pattern 2020-09-22 16:50:46 +08:00
Mike
a1515b3b52 finish builder and chain pattern 2020-09-22 11:13:25 +08:00
Mike
93aa1046aa translate decorator and factory method pattern in Chinese 2020-09-11 09:34:11 +08:00
13 changed files with 789 additions and 17 deletions

View File

@@ -1222,6 +1222,33 @@
"contributions": [
"doc"
]
},
{
"login": "Ascenio",
"name": "Ascênio",
"avatar_url": "https://avatars1.githubusercontent.com/u/7662016?v=4",
"profile": "https://github.com/Ascenio",
"contributions": [
"review"
]
},
{
"login": "dsibilio",
"name": "Domenico Sibilio",
"avatar_url": "https://avatars2.githubusercontent.com/u/24280982?v=4",
"profile": "https://www.linkedin.com/in/domenico-sibilio/",
"contributions": [
"doc"
]
},
{
"login": "akashchandwani",
"name": "Akash Chandwani",
"avatar_url": "https://avatars2.githubusercontent.com/u/3483277?v=4",
"profile": "https://github.com/akashchandwani",
"contributions": [
"review"
]
}
],
"contributorsPerLine": 4,

View File

@@ -30,29 +30,43 @@ on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
# Disabling shallow clone for improving relevancy of SonarQube reporting
fetch-depth: 0
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Cache SonarCloud packages
uses: actions/cache@v2
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Some tests need screen access
- name: Install xvfb
run: sudo apt-get install -y xvfb
# The SonarQube analysis is only for the master branch of the main repository.
# SonarQube scan does not work for forked repositories try changing it to xvfb-run mvn clean verify
# See https://jira.sonarsource.com/browse/MMF-1371

View File

@@ -10,7 +10,7 @@
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
[![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-134-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-137-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
# Introduction
@@ -31,7 +31,7 @@ This site showcases Java Design Patterns. The solutions have been developed by
experienced programmers and architects from the open source community. The
patterns can be browsed by their high level descriptions or by looking at their
source code. The source code examples are well commented and can be thought as
programming tutorials how to implement a specific pattern. We use the most
programming tutorials on how to implement a specific pattern. We use the most
popular battle-proven open source Java technologies.
Before you dive into the material, you should be familiar with various
@@ -270,6 +270,11 @@ This project is licensed under the terms of the MIT license.
<tr>
<td align="center"><a href="https://github.com/swarajsaaj"><img src="https://avatars2.githubusercontent.com/u/6285049?v=4" width="100px;" alt=""/><br /><sub><b>Swaraj</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=swarajsaaj" title="Code">💻</a></td>
<td align="center"><a href="http://christophflick.de"><img src="https://avatars0.githubusercontent.com/u/4465376?v=4" width="100px;" alt=""/><br /><sub><b>Christoph Flick</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=ChFlick" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/Ascenio"><img src="https://avatars1.githubusercontent.com/u/7662016?v=4" width="100px;" alt=""/><br /><sub><b>Ascênio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AAscenio" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://www.linkedin.com/in/domenico-sibilio/"><img src="https://avatars2.githubusercontent.com/u/24280982?v=4" width="100px;" alt=""/><br /><sub><b>Domenico Sibilio</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=dsibilio" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/akashchandwani"><img src="https://avatars2.githubusercontent.com/u/3483277?v=4" width="100px;" alt=""/><br /><sub><b>Akash Chandwani</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3Aakashchandwani" title="Reviewed Pull Requests">👀</a></td>
</tr>
</table>

View File

@@ -45,7 +45,7 @@ public class SpaceStationMir extends GameObject {
@Override
public void collisionResolve(FlamingAsteroid asteroid) {
LOGGER.info(AppConstants.HITS, " {} is damaged! {} is set on fire!", asteroid.getClass()
LOGGER.info(AppConstants.HITS + " {} is damaged! {} is set on fire!", asteroid.getClass()
.getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName(), this.getClass()
.getSimpleName());
@@ -55,14 +55,14 @@ public class SpaceStationMir extends GameObject {
@Override
public void collisionResolve(Meteoroid meteoroid) {
LOGGER.info(AppConstants.HITS, " {} is damaged!", meteoroid.getClass().getSimpleName(),
LOGGER.info(AppConstants.HITS + " {} is damaged!", meteoroid.getClass().getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName());
setDamaged(true);
}
@Override
public void collisionResolve(SpaceStationMir mir) {
LOGGER.info(AppConstants.HITS, " {} is damaged!", mir.getClass().getSimpleName(),
LOGGER.info(AppConstants.HITS + " {} is damaged!", mir.getClass().getSimpleName(),
this.getClass().getSimpleName(), this.getClass().getSimpleName());
setDamaged(true);
}

View File

@@ -29,6 +29,6 @@ Use the Event Sourcing pattern when
## Credits
* [Martin Fowler - Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html)
* [Event Sourcing | Microsoft Docs](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
* [Event Sourcing in Microsoft's documentation](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
* [Reference 3: Introducing Event Sourcing](https://msdn.microsoft.com/en-us/library/jj591559.aspx)
* [Event Sourcing pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)

View File

@@ -35,11 +35,6 @@
</parent>
<artifactId>trampoline</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>

View File

@@ -98,12 +98,12 @@ public interface Trampoline<T> {
return trampoline(this);
}
T trampoline(final Trampoline<T> trampoline) {
private T trampoline(final Trampoline<T> trampoline) {
return Stream.iterate(trampoline, Trampoline::jump)
.filter(Trampoline::complete)
.findFirst()
.map(Trampoline::result)
.orElseThrow();
.get();
}
};
}

View File

@@ -23,10 +23,9 @@
package com.iluwatar.trampoline;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
/**
* Test for trampoline pattern.
@@ -37,7 +36,7 @@ public class TrampolineAppTest {
@Test
public void testTrampolineWithFactorialFunction() {
long result = TrampolineApp.loop(10, 1).result();
assertEquals("Be equal", 3628800, result);
assertEquals(3_628_800, result);
}
}

139
zh/builder/README.md Normal file
View File

@@ -0,0 +1,139 @@
---
layout: pattern
title: Builder
folder: builder
permalink: /patterns/builder/
categories: Creational
tags:
- Gang of Four
---
## 目的
将复杂对象的构造与其表示分开,以便同一构造过程可以创建不同的表示。
## 解释
现实世界例子
> 想象一个角色扮演游戏的角色生成器。最简单的选择是让计算机为你创建角色。但是如果你想选择一些像专业,性别,发色等角色细节时,这个角色生成就变成了一个渐进的过程。当所有选择完成时,该过程也将完成。
用通俗的话说
> 允许你创建不同口味的对象同时避免构造器污染。当一个对象可能有几种口味,或者一个对象的创建涉及到很多步骤时会很有用。
维基百科说
> 建造者模式是一种对象创建的软件设计模式,旨在为伸缩构造器反模式寻找一个解决方案。
说了这么多,让我补充一下什么是伸缩构造函数反模式。我们肯定都见过像下面这样的构造器:
```java
public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) {
}
```
就像你看到的构造器参数的数量很快就会失控同时参数的排列方式可能变得难以理解。另外,如果您将来希望添加更多选项,则此参数列表可能会继续增长。这就被称伸缩构造器反模式。
**编程示例**
明智的选择是使用建造者模式。首先我们有一个英雄要创建。
```java
public final class Hero {
private final Profession profession;
private final String name;
private final HairType hairType;
private final HairColor hairColor;
private final Armor armor;
private final Weapon weapon;
private Hero(Builder builder) {
this.profession = builder.profession;
this.name = builder.name;
this.hairColor = builder.hairColor;
this.hairType = builder.hairType;
this.weapon = builder.weapon;
this.armor = builder.armor;
}
}
```
然后我们有创建者
```java
public static class Builder {
private final Profession profession;
private final String name;
private HairType hairType;
private HairColor hairColor;
private Armor armor;
private Weapon weapon;
public Builder(Profession profession, String name) {
if (profession == null || name == null) {
throw new IllegalArgumentException("profession and name can not be null");
}
this.profession = profession;
this.name = name;
}
public Builder withHairType(HairType hairType) {
this.hairType = hairType;
return this;
}
public Builder withHairColor(HairColor hairColor) {
this.hairColor = hairColor;
return this;
}
public Builder withArmor(Armor armor) {
this.armor = armor;
return this;
}
public Builder withWeapon(Weapon weapon) {
this.weapon = weapon;
return this;
}
public Hero build() {
return new Hero(this);
}
}
```
然后可以这样使用
```java
var mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK).withWeapon(Weapon.DAGGER).build();
```
## 类图
![alt text](../../builder/etc/builder.urm.png "Builder class diagram")
## 适用性
使用建造者模式当
* 创建复杂对象的算法应独立于组成对象的零件及其组装方式
* 构造过程必须允许所构造的对象具有不同的表示形式
## Java世界例子
* [java.lang.StringBuilder](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)
* [java.nio.ByteBuffer](http://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#put-byte-) as well as similar buffers such as FloatBuffer, IntBuffer and so on.
* [java.lang.StringBuffer](http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html#append-boolean-)
* All implementations of [java.lang.Appendable](http://docs.oracle.com/javase/8/docs/api/java/lang/Appendable.html)
* [Apache Camel builders](https://github.com/apache/camel/tree/0e195428ee04531be27a0b659005e3aa8d159d23/camel-core/src/main/java/org/apache/camel/builder)
* [Apache Commons Option.Builder](https://commons.apache.org/proper/commons-cli/apidocs/org/apache/commons/cli/Option.Builder.html)
## 鸣谢
* [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)
* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)
* [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)
* [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)

159
zh/chain/README.md Normal file
View File

@@ -0,0 +1,159 @@
---
layout: pattern
title: Chain of responsibility
folder: chain
permalink: /patterns/chain/
categories: Behavioral
tags:
- Gang of Four
---
## 目的
通过给多个对象一个处理请求的机会,避免请求的发送者和它的接收者耦合。串联接收对象并在链条中传递请求直到一个对象处理它。
## 解释
真实世界例子
> 兽王大声命令他的军队。最近响应的是指挥官,然后是军官,然后是士兵。指挥官,军官,士兵这里就形成了一个责任链。
通俗的说
> 它帮助构建一串对象。请求从一个对象中进入并结束然后进入到一个个对象中直到找到合适的处理器。
维基百科说
> 在面向对象设计中,责任链模式是一种由源命令对象和一系列处理对象组成的设计模式。每个处理对象包含了其定义的可处理的命令对象类型的逻辑。剩下的会传递给链条中的下一个处理对象。
**程序示例**
用上面的兽人来翻译我们的示例。首先我们有请求类
```java
public class Request {
private final RequestType requestType;
private final String requestDescription;
private boolean handled;
public Request(final RequestType requestType, final String requestDescription) {
this.requestType = Objects.requireNonNull(requestType);
this.requestDescription = Objects.requireNonNull(requestDescription);
}
public String getRequestDescription() { return requestDescription; }
public RequestType getRequestType() { return requestType; }
public void markHandled() { this.handled = true; }
public boolean isHandled() { return this.handled; }
@Override
public String toString() { return getRequestDescription(); }
}
public enum RequestType {
DEFEND_CASTLE, TORTURE_PRISONER, COLLECT_TAX
}
```
然后是请求处理器的层次结构
```java
public abstract class RequestHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestHandler.class);
private final RequestHandler next;
public RequestHandler(RequestHandler next) {
this.next = next;
}
public void handleRequest(Request req) {
if (next != null) {
next.handleRequest(req);
}
}
protected void printHandling(Request req) {
LOGGER.info("{} handling request \"{}\"", this, req);
}
@Override
public abstract String toString();
}
public class OrcCommander extends RequestHandler {
public OrcCommander(RequestHandler handler) {
super(handler);
}
@Override
public void handleRequest(Request req) {
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
printHandling(req);
req.markHandled();
} else {
super.handleRequest(req);
}
}
@Override
public String toString() {
return "Orc commander";
}
}
// OrcOfficer和OrcSoldier的定义与OrcCommander类似
```
然后我们有兽王下达命令并形成链条
```java
public class OrcKing {
RequestHandler chain;
public OrcKing() {
buildChain();
}
private void buildChain() {
chain = new OrcCommander(new OrcOfficer(new OrcSoldier(null)));
}
public void makeRequest(Request req) {
chain.handleRequest(req);
}
}
```
然后这样使用它
```java
var king = new OrcKing();
king.makeRequest(new Request(RequestType.DEFEND_CASTLE, "defend castle")); // Orc commander handling request "defend castle"
king.makeRequest(new Request(RequestType.TORTURE_PRISONER, "torture prisoner")); // Orc officer handling request "torture prisoner"
king.makeRequest(new Request(RequestType.COLLECT_TAX, "collect tax")); // Orc soldier handling request "collect tax"
```
## 类图
![alt text](../../chain/etc/chain.urm.png "Chain of Responsibility class diagram")
## 适用性
使用责任链模式当
* 多于一个对象可能要处理请求,并且处理器并不知道一个优先级。处理器应自动确定。
* 你想对多个对象之一发出请求而无需明确指定接收者
* 处理请求的对象集合应该被动态指定时
## Java世界例子
* [java.util.logging.Logger#log()](http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log%28java.util.logging.Level,%20java.lang.String%29)
* [Apache Commons Chain](https://commons.apache.org/proper/commons-chain/index.html)
* [javax.servlet.Filter#doFilter()](http://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html#doFilter-javax.servlet.ServletRequest-javax.servlet.ServletResponse-javax.servlet.FilterChain-)
## 鸣谢
* [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)
* [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)

139
zh/decorator/README.md Normal file
View File

@@ -0,0 +1,139 @@
---
layout: pattern
title: Decorator
folder: decorator
permalink: /patterns/decorator/
categories: Structural
tags:
- Gang Of Four
- Extensibility
---
## 或称
包装器
## 目的
动态的为对象附加额外的职责。装饰器为子类提供了灵活的替代方案,以扩展功能。
## 解释
真实世界例子
> 附近的山丘上住着一个愤怒的巨魔。通常它是徒手的,但有时它有武器。为了武装巨魔不必创建新的巨魔,而是用合适的武器动态的装饰它。
通俗的说
> 装饰者模式让你可以在运行时通过把对象包装进一个装饰类对象中来动态的改变一个对象的行为。
维基百科说
> 在面向对象的编程中,装饰器模式是一种设计模式,它允许将行为静态或动态地添加到单个对象中,而不会影响同一类中其他对象的行为。装饰器模式通常对于遵守单一责任原则很有用,因为它允许将功能划分到具有唯一关注领域的类之间。
**程序示例**
以巨魔的为例。首先我有有一个简单的巨魔,实现了巨魔接口。
程序mple. First of all we have a simple troll implementing the troll interface
```java
public interface Troll {
void attack();
int getAttackPower();
void fleeBattle();
}
public class SimpleTroll implements Troll {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTroll.class);
@Override
public void attack() {
LOGGER.info("The troll tries to grab you!");
}
@Override
public int getAttackPower() {
return 10;
}
@Override
public void fleeBattle() {
LOGGER.info("The troll shrieks in horror and runs away!");
}
}
```
下面我们想为巨魔添加球棒。我们可以用装饰者来动态的实现。
```java
public class ClubbedTroll implements Troll {
private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);
private final Troll decorated;
public ClubbedTroll(Troll decorated) {
this.decorated = decorated;
}
@Override
public void attack() {
decorated.attack();
LOGGER.info("The troll swings at you with a club!");
}
@Override
public int getAttackPower() {
return decorated.getAttackPower() + 10;
}
@Override
public void fleeBattle() {
decorated.fleeBattle();
}
}
```
这里是巨魔的实战
```java
// simple troll
var troll = new SimpleTroll();
troll.attack(); // The troll tries to grab you!
troll.fleeBattle(); // The troll shrieks in horror and runs away!
// change the behavior of the simple troll by adding a decorator
var clubbedTroll = new ClubbedTroll(troll);
clubbedTroll.attack(); // The troll tries to grab you! The troll swings at you with a club!
clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!
```
## 类图
![alt text](../../decorator/etc/decorator.urm.png "Decorator pattern class diagram")
## 适用性
使用装饰者
* 动态透明地向单个对象添加职责,即不影响其他对象
* 对于可以撤销的责任
* 当通过子类化进行扩展是不切实际的。有时可能会有大量的独立扩展,并且会产生大量的子类来支持每种组合。 否则类定义可能被隐藏或无法用于子类化。
## 教程
* [Decorator Pattern Tutorial](https://www.journaldev.com/1540/decorator-design-pattern-in-java-example)
## Java世界的例子
* [java.io.InputStream](http://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html), [java.io.OutputStream](http://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html),
[java.io.Reader](http://docs.oracle.com/javase/8/docs/api/java/io/Reader.html) and [java.io.Writer](http://docs.oracle.com/javase/8/docs/api/java/io/Writer.html)
* [java.util.Collections#synchronizedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedCollection-java.util.Collection-)
* [java.util.Collections#unmodifiableXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableCollection-java.util.Collection-)
* [java.util.Collections#checkedXXX()](http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedCollection-java.util.Collection-java.lang.Class-)
## 鸣谢
* [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)
* [Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions](https://www.amazon.com/gp/product/1937785467/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1937785467&linkCode=as2&tag=javadesignpat-20&linkId=7e4e2fb7a141631491534255252fd08b)
* [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)
* [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)
* [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)
* [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)

207
zh/facade/README.md Normal file
View File

@@ -0,0 +1,207 @@
---
layout: pattern
title: Facade
folder: facade
permalink: /patterns/facade/
categories: Structural
tags:
- Gang Of Four
- Decoupling
---
## 目的
为一个子系统中的一系列接口提供一个统一的接口。外观定义了一个更高级别的接口以便子系统更容易使用。
## 解释
真实世界的例子
> 一个金矿是怎么工作的?“嗯,矿工下去然后挖金子!”你说。这是你所相信的因为你在使用一个金矿对外提供的一个简单接口,在内部它要却要做很多事情。这个简单的接口对复杂的子系统来说就是一个外观。
用通俗的话说
> 外观模式为一个复杂的子系统提供一个简单的接口。
维基百科说
> 外观是为很大体量的代码(比如类库)提供简单接口的一种对象。
**程序示例**
使用上面金矿的例子。这里我们有矮人的矿工等级制度。
```java
public abstract class DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenMineWorker.class);
public void goToSleep() {
LOGGER.info("{} goes to sleep.", name());
}
public void wakeUp() {
LOGGER.info("{} wakes up.", name());
}
public void goHome() {
LOGGER.info("{} goes home.", name());
}
public void goToMine() {
LOGGER.info("{} goes to the mine.", name());
}
private void action(Action action) {
switch (action) {
case GO_TO_SLEEP:
goToSleep();
break;
case WAKE_UP:
wakeUp();
break;
case GO_HOME:
goHome();
break;
case GO_TO_MINE:
goToMine();
break;
case WORK:
work();
break;
default:
LOGGER.info("Undefined action");
break;
}
}
public void action(Action... actions) {
Arrays.stream(actions).forEach(this::action);
}
public abstract void work();
public abstract String name();
enum Action {
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
}
}
public class DwarvenTunnelDigger extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenTunnelDigger.class);
@Override
public void work() {
LOGGER.info("{} creates another promising tunnel.", name());
}
@Override
public String name() {
return "Dwarven tunnel digger";
}
}
public class DwarvenGoldDigger extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenGoldDigger.class);
@Override
public void work() {
LOGGER.info("{} digs for gold.", name());
}
@Override
public String name() {
return "Dwarf gold digger";
}
}
public class DwarvenCartOperator extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenCartOperator.class);
@Override
public void work() {
LOGGER.info("{} moves gold chunks out of the mine.", name());
}
@Override
public String name() {
return "Dwarf cart operator";
}
}
```
为了操纵所有这些矿工我们有了这个外观
```java
public class DwarvenGoldmineFacade {
private final List<DwarvenMineWorker> workers;
public DwarvenGoldmineFacade() {
workers = List.of(
new DwarvenGoldDigger(),
new DwarvenCartOperator(),
new DwarvenTunnelDigger());
}
public void startNewDay() {
makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);
}
public void digOutGold() {
makeActions(workers, DwarvenMineWorker.Action.WORK);
}
public void endDay() {
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
}
private static void makeActions(Collection<DwarvenMineWorker> workers,
DwarvenMineWorker.Action... actions) {
workers.forEach(worker -> worker.action(actions));
}
}
```
现在来使用外观
```java
DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();
facade.startNewDay();
// Dwarf gold digger wakes up.
// Dwarf gold digger goes to the mine.
// Dwarf cart operator wakes up.
// Dwarf cart operator goes to the mine.
// Dwarven tunnel digger wakes up.
// Dwarven tunnel digger goes to the mine.
facade.digOutGold();
// Dwarf gold digger digs for gold.
// Dwarf cart operator moves gold chunks out of the mine.
// Dwarven tunnel digger creates another promising tunnel.
facade.endDay();
// Dwarf gold digger goes home.
// Dwarf gold digger goes to sleep.
// Dwarf cart operator goes home.
// Dwarf cart operator goes to sleep.
// Dwarven tunnel digger goes home.
// Dwarven tunnel digger goes to sleep.
```
## 类图
![alt text](../../facade/etc/facade.urm.png "Facade pattern class diagram")
## 适用性
使用外观模式当
* 你想为一个复杂的子系统提供一个简单的接口。随着子系统的发展,它们通常会变得更加复杂。多数模式在应用时会导致更多和更少的类。这使子系统更可重用,更易于自定义,但是对于不需要自定义它的客户来说,使用它也变得更加困难。 外观可以提供子系统的简单默认视图,足以满足大多数客户端的需求。只有需要更多可定制性的客户才需要查看外观外的东西(原子系统提供的接口)。
* 客户端与抽象的实现类之间存在许多依赖关系。 引入外观以使子系统与客户端和其他子系统分离,从而提高子系统的独立性和可移植性。
* 您想对子系统进行分层。 使用外观来定义每个子系统级别的入口点。 如果子系统是相关的,则可以通过使子系统仅通过其外观相互通信来简化它们之间的依赖性。
## 鸣谢
* [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)
* [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)

View File

@@ -0,0 +1,88 @@
---
layout: pattern
title: Factory Method
folder: factory-method
permalink: /patterns/factory-method/
categories: Creational
tags:
- Extensibility
- Gang Of Four
---
## Also known as
# 或称
虚拟构造器
## 目的
为创建一个对象定义一个接口,但是让子类决定实例化哪个类。工厂方法允许类将实例化延迟到子类。
## 解释
真实世界例子
> 铁匠生产武器。精灵需要精灵武器,而兽人需要兽人武器。根据客户来召唤正确类型的铁匠。
通俗的说
> 它为类提供了一种把实例化的逻辑委托给子类的方式。
维基百科上说
> 在基于类的编程中,工厂方法模式是一种创建型设计模式用来解决创建对象的问题,而不需要指定将要创建对象的确切类。这是通过调用工厂方法创建对象来完成的,而不是通过调用构造器。该工厂方法在接口中指定并由子类实现,或者在基类实现并可以选择由子类重写。
**程序示例**
以上面的铁匠为例,首先我们有铁匠的接口和一些它的实现。
```java
public interface Blacksmith {
Weapon manufactureWeapon(WeaponType weaponType);
}
public class ElfBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return ELFARSENAL.get(weaponType);
}
}
public class OrcBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return ORCARSENAL.get(weaponType);
}
}
```
现在随着客户的到来,会召唤出正确类型的铁匠并制造出要求的武器。
```java
var blacksmith = new ElfBlacksmith();
blacksmith.manufactureWeapon(WeaponType.SPEAR);
blacksmith.manufactureWeapon(WeaponType.AXE);
// Elvish weapons are created
```
## 类图
![alt text](../../factory-method/etc/factory-method.urm.png "Factory Method pattern class diagram")
## 适用性
使用工厂方法模式当
* 一个类无法预料它所要必须创建的对象的类
* 一个类想要它的子类来指定它要创建的对象
* 类将责任委派给几个帮助子类中的一个,而你想定位了解是具体之中的哪一个
## Java中的例子
* [java.util.Calendar](http://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#getInstance--)
* [java.util.ResourceBundle](http://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html#getBundle-java.lang.String-)
* [java.text.NumberFormat](http://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--)
* [java.nio.charset.Charset](http://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html#forName-java.lang.String-)
* [java.net.URLStreamHandlerFactory](http://docs.oracle.com/javase/8/docs/api/java/net/URLStreamHandlerFactory.html#createURLStreamHandler-java.lang.String-)
* [java.util.EnumSet](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html#of-E-)
* [javax.xml.bind.JAXBContext](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/JAXBContext.html#createMarshaller--)
## 鸣谢
* [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)
* [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)
* [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)