观察者模式从名字上来看大概就是一种通知与被通知的关系,其实代码思想也与其差不多,其核心思想就是有一个或N个观察者(Observer)和一个(或N个)被观察者(Observable 或 Subject),观察者以订阅方式来观察被观察者,当被观察者接到更新时(程序员控制或代码自动发出)将通知所有观察者来接受更新的内容。这就有点像一群学生(Observer,观察者)和书店老板(Observable 或 Subject,被观察者),当书店每次新进漫画杂志时,就会通知所有学生去购买。下面就看看如何用代码来实现这个事件。
观察者模式是另一种可被Lambda 表达式简化和改进的行为模式。在观察者模式中,被观察者持有一个观察者列表。当被观察者的状态发生改变,会通知观察者。观察者模式被大
量应用于基于MVC 的GUI 工具中,以此让模型状态发生变化时,自动刷新视图模块,达到二者之间的解耦。
观看GUI 模块自动刷新有点枯燥,我们要观察的对象是月球! NASA 和外星人都对登陆到月球上的东西感兴趣,都希望可以记录这些信息。NASA 希望确保阿波罗号上的航天员成功登月;外星人则希望在NASA 注意力分散之时进犯地球。
让我们先来定义观察者的API, 这里我将观察者称作LandingObserver。它只有一个
observeLanding 方法,当有东西登陆到月球上时会调用该方法
用于观察登陆到月球的组织的接口public interface LandingObserver { public void observeLanding(String name); }
被观察者是月球Moon,它持有一组LandingObserver 实例,有东西着陆时会通知这些观察者,还可以增加新的LandingObserver 实例观测Moon 对象
Moon 类当然不如现实世界中那么完美public class Moon { private final List<LandingObserver> observers = new ArrayList<>(); public void land(String name) { for (LandingObserver observer : observers) { observer.observeLanding(name); } } public void startSpying(LandingObserver observer) { observers.add(observer); } }
我们有两个具体的类实现了LandingObserver 接口,分别代表外星人和NASA检测着陆情况。前面提到过,监测到登陆后它们有不同的反应。
外星人观察到人类登陆月球
public class Aliens implements LandingObserver { @Override public void observeLanding(String name) { if (name.contains("Apollo")) { System.out.println("They're distracted, lets invade earth!"); } } } NASA 也能观察到有人登陆月球public class Nasa implements LandingObserver { @Override public void observeLanding(String name) { if (name.contains("Apollo")) { System.out.println("We made it!"); } } }
和前面的模式类似,在传统的例子中,用户代码需要有一层模板类,如果使用Lambda 表达式,就不用编写这些类了
使用类的方式构建用户代码 Moon moon = new Moon(); moon.startSpying(new Nasa()); moon.startSpying(new Aliens()); moon.land("An asteroid"); moon.land("Apollo 11"); 使用Lambda 表达式构建用户代码 Moon moon = new Moon(); moon.startSpying(name -> { if (name.contains("Apollo")) System.out.println("We made it!"); }); moon.startSpying(name -> { if (name.contains("Apollo")) System.out.println("They're distracted, lets invade earth!"); }); moon.land("An asteroid"); moon.land("Apollo 11");
还有一点值得思考,无论使用观察者模式或策略模式,实现时采用Lambda 表达式还是传统的类,取决于策略和观察者代码的复杂度。我这里所举的例子代码很简单,只是一两个
方法调用,很适合展示新的语言特性。然而在有些情况下,观察者本身就是一个很复杂的类,这时将很多代码塞进一个方法中会大大降低代码的可读性。
从某种角度来说,将大量代码塞进一个方法会让可读性变差是决定如何使用Lambda 表达式的黄金法则。之所以不在这里过分强调,是因为这也是编写一般方法时的黄金法则!
作者:芥末无疆sss
链接:https://www.jianshu.com/p/88dd90afa5d7
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
共同学习,写下你的评论
评论加载中...
作者其他优质文章