diff --git a/zh/observer/README.md b/zh/observer/README.md new file mode 100644 index 000000000..8a4b80a07 --- /dev/null +++ b/zh/observer/README.md @@ -0,0 +1,159 @@ +--- +layout: pattern +title: Observer +folder: observer +permalink: /patterns/observer/ +categories: Behavioral +tags: + - Gang Of Four + - Reactive +--- + +## Also known as +## 又被称为 + +家属,发布订阅模式 + +## 目的 + +定义一种一对多的对象依赖关系这样当一个对象改变状态时,所有依赖它的对象都将自动通知或更新。 + +## 解释 + +真实世界例子 + +> 在遥远的土地上生活着霍比特人和兽人的种族。他们都是户外生活的人所以他们密切关注天气的变化。可以说他们不断地关注着天气。 + +通俗的说 + +> 注册成为一个观察者以接收对象状态的改变。 + +维基百科说 + +> 观察者模式是这样的一种软件设计模式:它有一个被称为主题的对象,维护着一个所有依赖于它的依赖者清单,也就是观察者清单,当主题的状态发生改变时,主题通常会调用观察者的方法来自动通知观察者们。 + +**编程示例** + +让我们先来介绍天气观察者的接口以及我们的种族,兽人和霍比特人。 + +```java +public interface WeatherObserver { + + void update(WeatherType currentWeather); +} + +public class Orcs implements WeatherObserver { + + private static final Logger LOGGER = LoggerFactory.getLogger(Orcs.class); + + @Override + public void update(WeatherType currentWeather) { + LOGGER.info("The orcs are facing " + currentWeather.getDescription() + " weather now"); + } +} + +public class Hobbits implements WeatherObserver { + + private static final Logger LOGGER = LoggerFactory.getLogger(Hobbits.class); + + @Override + public void update(WeatherType currentWeather) { + switch (currentWeather) { + LOGGER.info("The hobbits are facing " + currentWeather.getDescription() + " weather now"); + } +} +``` + +然后这里是不断变化的天气。 + +```java +public class Weather { + + private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class); + + private WeatherType currentWeather; + private final List observers; + + public Weather() { + observers = new ArrayList<>(); + currentWeather = WeatherType.SUNNY; + } + + public void addObserver(WeatherObserver obs) { + observers.add(obs); + } + + public void removeObserver(WeatherObserver obs) { + observers.remove(obs); + } + + /** + * Makes time pass for weather. + */ + public void timePasses() { + var enumValues = WeatherType.values(); + currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length]; + LOGGER.info("The weather changed to {}.", currentWeather); + notifyObservers(); + } + + private void notifyObservers() { + for (var obs : observers) { + obs.update(currentWeather); + } + } +} +``` + +这是完整的示例。 + +```java + var weather = new Weather(); + weather.addObserver(new Orcs()); + weather.addObserver(new Hobbits()); + + weather.timePasses(); + // The weather changed to rainy. + // The orcs are facing rainy weather now + // The hobbits are facing rainy weather now + weather.timePasses(); + // The weather changed to windy. + // The orcs are facing windy weather now + // The hobbits are facing windy weather now + weather.timePasses(); + // The weather changed to cold. + // The orcs are facing cold weather now + // The hobbits are facing cold weather now + weather.timePasses(); + // The weather changed to sunny. + // The orcs are facing sunny weather now + // The hobbits are facing sunny weather now +``` + +## Class diagram +![alt text](../../observer/etc/observer.png "Observer") + +## 应用 +在下面任何一种情况下都可以使用观察者模式 + +* 当抽象具有两个方面时,一个方面依赖于另一个方面。将这些方面封装在单独的对象中,可以使你分别进行更改和重用 +* 当一个对象的改变的同时需要改变其他对象,同时你又不知道有多少对象需要改变时 +* 当一个对象可以通知其他对象而无需假设这些对象是谁时。换句话说,你不想让这些对象紧耦合。 + +## 典型用例 + +* 一个对象的改变导致其他对象的改变 + +## Java中的例子 + +* [java.util.Observer](http://docs.oracle.com/javase/8/docs/api/java/util/Observer.html) +* [java.util.EventListener](http://docs.oracle.com/javase/8/docs/api/java/util/EventListener.html) +* [javax.servlet.http.HttpSessionBindingListener](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionBindingListener.html) +* [RxJava](https://github.com/ReactiveX/RxJava) + +## 鸣谢 + +* [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) +* [Java Generics and Collections](https://www.amazon.com/gp/product/0596527756/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596527756&linkCode=as2&tag=javadesignpat-20&linkId=246e5e2c26fe1c3ada6a70b15afcb195) +* [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) diff --git a/zh/strategy/README.md b/zh/strategy/README.md new file mode 100644 index 000000000..29fe2e4eb --- /dev/null +++ b/zh/strategy/README.md @@ -0,0 +1,136 @@ +--- +layout: pattern +title: Strategy +folder: strategy +permalink: /patterns/strategy/ +categories: Behavioral +tags: + - Gang of Four +--- + +## 又被称为 +政策(方针)模式 + +## 目的 + +定义一个家族算法,并封装好其中每一个,使它们可以互相替换。策略模式使算法的变化独立于使用它的客户。 + +## 解释 + +现实世界例子 + +> 屠龙是一项危险的职业。有经验将会使它变得简单。经验丰富的屠龙者对不同类型的龙有不同的战斗策略。 + +直白点说 + +> 策略模式允许在运行时选择最匹配的算法。 + +维基百科上说 + +> 在程序编程领域,策略模式(又叫政策模式)是一种启用在运行时选择算法的行为型软件设计模式。 + +**编程实例** + +让我们先介绍屠龙的策略模式接口和它的实现。 + +```java +@FunctionalInterface +public interface DragonSlayingStrategy { + + void execute(); +} + +public class MeleeStrategy implements DragonSlayingStrategy { + + private static final Logger LOGGER = LoggerFactory.getLogger(MeleeStrategy.class); + + @Override + public void execute() { + LOGGER.info("With your Excalibur you sever the dragon's head!"); + } +} + +public class ProjectileStrategy implements DragonSlayingStrategy { + + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectileStrategy.class); + + @Override + public void execute() { + LOGGER.info("You shoot the dragon with the magical crossbow and it falls dead on the ground!"); + } +} + +public class SpellStrategy implements DragonSlayingStrategy { + + private static final Logger LOGGER = LoggerFactory.getLogger(SpellStrategy.class); + + @Override + public void execute() { + LOGGER.info("You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"); + } +} +``` + +现在有一个强力的屠龙者要基于上面的组件来选择他的战斗策略。 + +```java +public class DragonSlayer { + + private DragonSlayingStrategy strategy; + + public DragonSlayer(DragonSlayingStrategy strategy) { + this.strategy = strategy; + } + + public void changeStrategy(DragonSlayingStrategy strategy) { + this.strategy = strategy; + } + + public void goToBattle() { + strategy.execute(); + } +} +``` + +最后是屠龙者的行动。 + +```java + LOGGER.info("Green dragon spotted ahead!"); + var dragonSlayer = new DragonSlayer(new MeleeStrategy()); + dragonSlayer.goToBattle(); + LOGGER.info("Red dragon emerges."); + dragonSlayer.changeStrategy(new ProjectileStrategy()); + dragonSlayer.goToBattle(); + LOGGER.info("Black dragon lands before you."); + dragonSlayer.changeStrategy(new SpellStrategy()); + dragonSlayer.goToBattle(); + + // Green dragon spotted ahead! + // With your Excalibur you sever the dragon's head! + // Red dragon emerges. + // You shoot the dragon with the magical crossbow and it falls dead on the ground! + // Black dragon lands before you. + // You cast the spell of disintegration and the dragon vaporizes in a pile of dust! +``` + +## 类图 +![alt text](../../strategy/etc/strategy_1.png "Strategy") + +## 应用 +使用策略模式当 + +* 许多相关的类只是行为不同。策略模式提供了一种为一种类配置多种行为的能力。 +* 你需要一种算法的不同变体。比如,你可能定义反应不用时间空间权衡的算法。当这些算法的变体使用类的层次结构来实现时就可以使用策略模式。 +* 一个算法使用的数据客户不应该对其知晓。使用策略模式来避免暴露复杂的,特定于算法的数据结构。 +* 一个类定义了许多行为,这些行为在其操作中展现为多个条件语句。移动相关的条件分支到它们分别的策略类中来代替这些条件语句。 + +## 教学 + +* [Strategy Pattern Tutorial](https://www.journaldev.com/1754/strategy-design-pattern-in-java-example-tutorial) + +## 鸣谢 + +* [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) +* [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)