Compare commits
7 Commits
all-contri
...
all-contri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9648d70628 | ||
|
|
0c96f4d295 | ||
|
|
9ad3aa4240 | ||
|
|
4e3ab7d91b | ||
|
|
e69408e220 | ||
|
|
cfe2854522 | ||
|
|
043b0e3f01 |
@@ -1296,15 +1296,6 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"doc"
|
"doc"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "omk13",
|
|
||||||
"name": "Omar Karazoun",
|
|
||||||
"avatar_url": "https://avatars0.githubusercontent.com/u/59054172?v=4",
|
|
||||||
"profile": "https://github.com/omk13",
|
|
||||||
"contributions": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 4,
|
"contributorsPerLine": 4,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
[](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns)
|
||||||
[](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](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-BADGE:START - Do not remove or modify this section -->
|
||||||
[](#contributors-)
|
[](#contributors-)
|
||||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
@@ -282,7 +282,6 @@ This project is licensed under the terms of the MIT license.
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://ibrahimalii.github.io/"><img src="https://avatars2.githubusercontent.com/u/21141301?v=4" width="100px;" alt=""/><br /><sub><b>Ibrahim ali abdelghany</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AibrahimAlii" title="Reviewed Pull Requests">👀</a></td>
|
<td align="center"><a href="https://ibrahimalii.github.io/"><img src="https://avatars2.githubusercontent.com/u/21141301?v=4" width="100px;" alt=""/><br /><sub><b>Ibrahim ali abdelghany</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/pulls?q=is%3Apr+reviewed-by%3AibrahimAlii" title="Reviewed Pull Requests">👀</a></td>
|
||||||
<td align="center"><a href="https://github.com/gkulkarni2020"><img src="https://avatars3.githubusercontent.com/u/5161548?v=4" width="100px;" alt=""/><br /><sub><b>Girish Kulkarni</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gkulkarni2020" title="Documentation">📖</a></td>
|
<td align="center"><a href="https://github.com/gkulkarni2020"><img src="https://avatars3.githubusercontent.com/u/5161548?v=4" width="100px;" alt=""/><br /><sub><b>Girish Kulkarni</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=gkulkarni2020" title="Documentation">📖</a></td>
|
||||||
<td align="center"><a href="https://github.com/omk13"><img src="https://avatars0.githubusercontent.com/u/59054172?v=4" width="100px;" alt=""/><br /><sub><b>Omar Karazoun</b></sub></a><br /><a href="https://github.com/iluwatar/java-design-patterns/commits?author=omk13" title="Code">💻</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ Now on the client code we can create different types of cars using the factory c
|
|||||||
var car1 = CarsFactory.getCar(CarType.FORD);
|
var car1 = CarsFactory.getCar(CarType.FORD);
|
||||||
var car2 = CarsFactory.getCar(CarType.FERRARI);
|
var car2 = CarsFactory.getCar(CarType.FERRARI);
|
||||||
LOGGER.info(car1.getDescription());
|
LOGGER.info(car1.getDescription());
|
||||||
LOGGER.info(car2.getDescription());
|
LOGGER.info(car2.getDescription());;
|
||||||
```
|
```
|
||||||
|
|
||||||
Program output:
|
Program output:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,10 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.Before;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.Test;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FixedStepGameLoop unit test class.
|
* FixedStepGameLoop unit test class.
|
||||||
@@ -36,12 +35,12 @@ public class FixedStepGameLoopTest {
|
|||||||
|
|
||||||
private FixedStepGameLoop gameLoop;
|
private FixedStepGameLoop gameLoop;
|
||||||
|
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
gameLoop = new FixedStepGameLoop();
|
gameLoop = new FixedStepGameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
gameLoop = null;
|
gameLoop = null;
|
||||||
}
|
}
|
||||||
@@ -49,7 +48,7 @@ public class FixedStepGameLoopTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testUpdate() {
|
public void testUpdate() {
|
||||||
gameLoop.update();
|
gameLoop.update();
|
||||||
assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);
|
Assert.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,10 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.Before;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FrameBasedGameLoop unit test class.
|
* FrameBasedGameLoop unit test class.
|
||||||
@@ -35,19 +35,19 @@ public class FrameBasedGameLoopTest {
|
|||||||
|
|
||||||
private FrameBasedGameLoop gameLoop;
|
private FrameBasedGameLoop gameLoop;
|
||||||
|
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
gameLoop = new FrameBasedGameLoop();
|
gameLoop = new FrameBasedGameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
gameLoop = null;
|
gameLoop = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testUpdate() {
|
public void testUpdate() {
|
||||||
gameLoop.update();
|
gameLoop.update();
|
||||||
assertEquals(0.5f, gameLoop.controller.getBulletPosition(), 0);
|
Assert.assertEquals(0.5f, gameLoop.controller.getBulletPosition(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,33 +23,34 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.After;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class GameControllerTest {
|
public class GameControllerTest {
|
||||||
|
|
||||||
private GameController controller;
|
private GameController controller;
|
||||||
|
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
controller = new GameController();
|
controller = new GameController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
controller = null;
|
controller = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testMoveBullet() {
|
public void testMoveBullet() {
|
||||||
controller.moveBullet(1.5f);
|
controller.moveBullet(1.5f);
|
||||||
Assertions.assertEquals(1.5f, controller.bullet.getPosition(), 0);
|
Assert.assertEquals(1.5f, controller.bullet.getPosition(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testGetBulletPosition() {
|
public void testGetBulletPosition() {
|
||||||
Assertions.assertEquals(controller.bullet.getPosition(), controller.getBulletPosition(), 0);
|
Assert.assertEquals(controller.bullet.getPosition(), controller.getBulletPosition(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,10 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.After;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GameLoop unit test class.
|
* GameLoop unit test class.
|
||||||
@@ -37,7 +38,7 @@ public class GameLoopTest {
|
|||||||
/**
|
/**
|
||||||
* Create mock implementation of GameLoop.
|
* Create mock implementation of GameLoop.
|
||||||
*/
|
*/
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
gameLoop = new GameLoop() {
|
gameLoop = new GameLoop() {
|
||||||
@Override
|
@Override
|
||||||
@@ -45,26 +46,26 @@ public class GameLoopTest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
gameLoop = null;
|
gameLoop = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testRun() {
|
public void testRun() {
|
||||||
gameLoop.run();
|
gameLoop.run();
|
||||||
Assertions.assertEquals(GameStatus.RUNNING, gameLoop.status);
|
Assert.assertEquals(GameStatus.RUNNING, gameLoop.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testStop() {
|
public void testStop() {
|
||||||
gameLoop.stop();
|
gameLoop.stop();
|
||||||
Assertions.assertEquals(GameStatus.STOPPED, gameLoop.status);
|
Assert.assertEquals(GameStatus.STOPPED, gameLoop.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testIsGameRunning() {
|
public void testIsGameRunning() {
|
||||||
Assertions.assertFalse(gameLoop.isGameRunning());
|
Assert.assertFalse(gameLoop.isGameRunning());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,11 @@
|
|||||||
|
|
||||||
package com.iluwatar.gameloop;
|
package com.iluwatar.gameloop;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.After;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VariableStepGameLoop unit test class.
|
* VariableStepGameLoop unit test class.
|
||||||
@@ -34,19 +36,19 @@ public class VariableStepGameLoopTest {
|
|||||||
|
|
||||||
private VariableStepGameLoop gameLoop;
|
private VariableStepGameLoop gameLoop;
|
||||||
|
|
||||||
@BeforeEach
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
gameLoop = new VariableStepGameLoop();
|
gameLoop = new VariableStepGameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
gameLoop = null;
|
gameLoop = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@org.junit.jupiter.api.Test
|
@Test
|
||||||
public void testUpdate() {
|
public void testUpdate() {
|
||||||
gameLoop.update(20L);
|
gameLoop.update(20L);
|
||||||
Assertions.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);
|
Assert.assertEquals(0.01f, gameLoop.controller.getBulletPosition(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
---
|
|
||||||
layout: pattern
|
|
||||||
title: Bridge
|
|
||||||
folder: bridge
|
|
||||||
permalink: /patterns/bridge/
|
|
||||||
categories: Structural
|
|
||||||
tags:
|
|
||||||
- Gang of Four
|
|
||||||
---
|
|
||||||
|
|
||||||
## 又被称为
|
|
||||||
|
|
||||||
手柄/身体模式
|
|
||||||
|
|
||||||
## 目的
|
|
||||||
|
|
||||||
将抽象与其实现分离,以便二者可以独立变化。
|
|
||||||
|
|
||||||
## 解释
|
|
||||||
|
|
||||||
真实世界例子
|
|
||||||
|
|
||||||
> 考虑一下你拥有一种具有不同附魔的武器,并且应该允许将具有不同附魔的不同武器混合使用。 你会怎么做? 为每个附魔创建每种武器的多个副本,还是只是创建单独的附魔并根据需要为武器设置它? 桥接模式使您可以进行第二次操作。
|
|
||||||
|
|
||||||
通俗的说
|
|
||||||
|
|
||||||
> 桥接模式是一个更推荐组合而不是继承的模式。将实现细节从一个层次结构推送到具有单独层次结构的另一个对象。
|
|
||||||
|
|
||||||
维基百科说
|
|
||||||
|
|
||||||
> 桥接模式是软件工程中使用的一种设计模式,旨在“将抽象与其实现分离,从而使两者可以独立变化”
|
|
||||||
|
|
||||||
**程序示例**
|
|
||||||
|
|
||||||
翻译一下上面的武器示例。下面我们有武器的类层级:
|
|
||||||
|
|
||||||
```java
|
|
||||||
public interface Weapon {
|
|
||||||
void wield();
|
|
||||||
void swing();
|
|
||||||
void unwield();
|
|
||||||
Enchantment getEnchantment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Sword implements Weapon {
|
|
||||||
|
|
||||||
private final Enchantment enchantment;
|
|
||||||
|
|
||||||
public Sword(Enchantment enchantment) {
|
|
||||||
this.enchantment = enchantment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void wield() {
|
|
||||||
LOGGER.info("The sword is wielded.");
|
|
||||||
enchantment.onActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swing() {
|
|
||||||
LOGGER.info("The sword is swinged.");
|
|
||||||
enchantment.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unwield() {
|
|
||||||
LOGGER.info("The sword is unwielded.");
|
|
||||||
enchantment.onDeactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Enchantment getEnchantment() {
|
|
||||||
return enchantment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Hammer implements Weapon {
|
|
||||||
|
|
||||||
private final Enchantment enchantment;
|
|
||||||
|
|
||||||
public Hammer(Enchantment enchantment) {
|
|
||||||
this.enchantment = enchantment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void wield() {
|
|
||||||
LOGGER.info("The hammer is wielded.");
|
|
||||||
enchantment.onActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void swing() {
|
|
||||||
LOGGER.info("The hammer is swinged.");
|
|
||||||
enchantment.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unwield() {
|
|
||||||
LOGGER.info("The hammer is unwielded.");
|
|
||||||
enchantment.onDeactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Enchantment getEnchantment() {
|
|
||||||
return enchantment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
这里是单独的附魔类结构:
|
|
||||||
|
|
||||||
```java
|
|
||||||
public interface Enchantment {
|
|
||||||
void onActivate();
|
|
||||||
void apply();
|
|
||||||
void onDeactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FlyingEnchantment implements Enchantment {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivate() {
|
|
||||||
LOGGER.info("The item begins to glow faintly.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply() {
|
|
||||||
LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeactivate() {
|
|
||||||
LOGGER.info("The item's glow fades.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SoulEatingEnchantment implements Enchantment {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivate() {
|
|
||||||
LOGGER.info("The item spreads bloodlust.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply() {
|
|
||||||
LOGGER.info("The item eats the soul of enemies.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeactivate() {
|
|
||||||
LOGGER.info("Bloodlust slowly disappears.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
这里是两种层次结构的实践:
|
|
||||||
|
|
||||||
```java
|
|
||||||
var enchantedSword = new Sword(new SoulEatingEnchantment());
|
|
||||||
enchantedSword.wield();
|
|
||||||
enchantedSword.swing();
|
|
||||||
enchantedSword.unwield();
|
|
||||||
// The sword is wielded.
|
|
||||||
// The item spreads bloodlust.
|
|
||||||
// The sword is swinged.
|
|
||||||
// The item eats the soul of enemies.
|
|
||||||
// The sword is unwielded.
|
|
||||||
// Bloodlust slowly disappears.
|
|
||||||
|
|
||||||
var hammer = new Hammer(new FlyingEnchantment());
|
|
||||||
hammer.wield();
|
|
||||||
hammer.swing();
|
|
||||||
hammer.unwield();
|
|
||||||
// The hammer is wielded.
|
|
||||||
// The item begins to glow faintly.
|
|
||||||
// The hammer is swinged.
|
|
||||||
// The item flies and strikes the enemies finally returning to owner's hand.
|
|
||||||
// The hammer is unwielded.
|
|
||||||
// The item's glow fades.
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 类图
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 适用性
|
|
||||||
|
|
||||||
使用桥接模式当
|
|
||||||
|
|
||||||
* 你想永久性的避免抽象和他的实现之间的绑定。有可能是这种情况,当实现需要被选择或者在运行时切换。
|
|
||||||
* 抽象和他们的实现应该能通过写子类来扩展。这种情况下,桥接模式让你可以组合不同的抽象和实现并独立的扩展他们。
|
|
||||||
* 对抽象的实现的改动应当不会对客户产生影响;也就是说,他们的代码不必重新编译。
|
|
||||||
* 你有种类繁多的类。这样的类层次结构表明需要将一个对象分为两部分。Rumbaugh 使用术语“嵌套归纳”来指代这种类层次结构。
|
|
||||||
* 你想在多个对象间分享一种实现(可能使用引用计数),这个事实应该对客户隐藏。一个简单的示例是Coplien的String类,其中多个对象可以共享同一字符串表示形式
|
|
||||||
|
|
||||||
## 教程
|
|
||||||
|
|
||||||
* [Bridge Pattern Tutorial](https://www.journaldev.com/1491/bridge-design-pattern-java)
|
|
||||||
|
|
||||||
## 鸣谢
|
|
||||||
|
|
||||||
* [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)
|
|
||||||
@@ -33,6 +33,8 @@ tags:
|
|||||||
|
|
||||||
以巨魔的为例。首先我有有一个简单的巨魔,实现了巨魔接口。
|
以巨魔的为例。首先我有有一个简单的巨魔,实现了巨魔接口。
|
||||||
|
|
||||||
|
程序mple. First of all we have a simple troll implementing the troll interface
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public interface Troll {
|
public interface Troll {
|
||||||
void attack();
|
void attack();
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
---
|
|
||||||
layout: pattern
|
|
||||||
title: Dependency Injection
|
|
||||||
folder: dependency-injection
|
|
||||||
permalink: /patterns/dependency-injection/
|
|
||||||
categories: Creational
|
|
||||||
tags:
|
|
||||||
- Decoupling
|
|
||||||
---
|
|
||||||
|
|
||||||
## 目的
|
|
||||||
|
|
||||||
依赖注入是一种软件设计模式,其中一个或多个依赖项(或服务)被注入或通过引用传递到一个依赖对象(或客户端)中,并成为客户端状态的一部分。该模式将客户的依赖关系的创建与其自身的行为分开,这使程序设计可以松散耦合,并遵循控制反转和单一职责原则。
|
|
||||||
|
|
||||||
## 解释
|
|
||||||
|
|
||||||
真实世界例子
|
|
||||||
|
|
||||||
> 老巫师喜欢不时地装满烟斗抽烟。 但是,他不想只依赖一个烟草品牌,而是希望能够互换使用它们。
|
|
||||||
|
|
||||||
通俗的说
|
|
||||||
|
|
||||||
> 依赖注入将客户端依赖的创建与其自身行为分开。
|
|
||||||
|
|
||||||
维基百科说
|
|
||||||
|
|
||||||
> 在软件工程中,依赖注入是一种对象接收其依赖的其他对象的技术。 这些其他对象称为依赖项。
|
|
||||||
|
|
||||||
**程序示例**
|
|
||||||
|
|
||||||
先介绍一下烟草接口和具体的品牌。
|
|
||||||
|
|
||||||
```java
|
|
||||||
public abstract class Tobacco {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(Tobacco.class);
|
|
||||||
|
|
||||||
public void smoke(Wizard wizard) {
|
|
||||||
LOGGER.info("{} smoking {}", wizard.getClass().getSimpleName(),
|
|
||||||
this.getClass().getSimpleName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SecondBreakfastTobacco extends Tobacco {
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RivendellTobacco extends Tobacco {
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OldTobyTobacco extends Tobacco {
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
下面是老巫师的类的层次结构。
|
|
||||||
|
|
||||||
```java
|
|
||||||
public interface Wizard {
|
|
||||||
|
|
||||||
void smoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AdvancedWizard implements Wizard {
|
|
||||||
|
|
||||||
private final Tobacco tobacco;
|
|
||||||
|
|
||||||
public AdvancedWizard(Tobacco tobacco) {
|
|
||||||
this.tobacco = tobacco;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void smoke() {
|
|
||||||
tobacco.smoke(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
最后我们可以看到给老巫师任意品牌的烟草是多么的简单。
|
|
||||||
|
|
||||||
```java
|
|
||||||
var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());
|
|
||||||
advancedWizard.smoke();
|
|
||||||
```
|
|
||||||
|
|
||||||
## 类图
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 适用性
|
|
||||||
|
|
||||||
使用依赖注入当:
|
|
||||||
|
|
||||||
- 当你需要从对象中移除掉具体的实现内容时
|
|
||||||
|
|
||||||
* 使用模拟对象或存根隔离地启用类的单元测试
|
|
||||||
|
|
||||||
## 鸣谢
|
|
||||||
|
|
||||||
* [Dependency Injection Principles, Practices, and Patterns](https://www.amazon.com/gp/product/161729473X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=161729473X&linkId=57079257a5c7d33755493802f3b884bd)
|
|
||||||
* [Clean Code: A Handbook of Agile Software Craftsmanship](https://www.amazon.com/gp/product/0132350882/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0132350882&linkCode=as2&tag=javadesignpat-20&linkId=2c390d89cc9e61c01b9e7005c7842871)
|
|
||||||
* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://www.amazon.com/gp/product/1788296257/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1788296257&linkId=4e9137a3bf722a8b5b156cce1eec0fc1)
|
|
||||||
* [Google Guice Tutorial: Open source Java based dependency injection framework](https://www.amazon.com/gp/product/B083P7DZ8M/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B083P7DZ8M&linkId=04f0f902c877921e45215b624a124bfe)
|
|
||||||
Reference in New Issue
Block a user