使用动机:
举个例子来说(不要钻牛角尖):红绿灯就是一个依赖于Subject的ConcreteSubject具体通知者,而车辆行人就是各个依赖于抽象Observer观察者类,当灯变色时,红绿灯调用车辆行人的update()方法其实都可以叫做run()方法,而车辆行人再根据红绿色的当前状态执行下一步行动,就而已做到。
如此,通知者和观察者都依赖于抽象,很好的实现了“依赖倒置”原则,在客户端维护和扩展上都相对于两个类相互依赖更方便。
而观察者模式的缺点:上面举例子中,“当灯变色时,红绿灯调用车辆行人的update()方法其实都可以叫做run()方法”,那么这样的话,红绿灯这个通知者还是要依赖于车辆行人的观察者。那么如果没有了车辆行人,那么“红绿灯调用车辆行人的update()方法”就没有办法执行,程序就进行不下去了,这是第一个缺点。第二个缺点:因为观察者依赖于通知者的抽象,那么子类肯定要具有相同的方法名才行,如果红绿灯坏了,这也是一个状态,那么就应该调用观察者修理工.run()方法,这样就牛头不对马嘴了,应该说调用观察者修理工repair()修理方法,但是既然是依赖于同一个抽象,那么方法名就一样,这样就导致无法编程下去了。
总结来说:1.观察者还是依赖于通知者。2.通知者依赖于抽象,必须具有相同方法名,不利于多类复用。
如此解决方法:使用委托
java中,并没有像c#中的delegate关键字,所以需要动态调用观察者的话需要用到反射(过程会相对C#更加复杂一些)。
还是举上面的例子使用委托:“当灯变色时,红绿灯调用车辆行人的update()方法其实都可以叫做run()方法”之后进行改动,加入一个EvenHandler委托类(就是交警),当灯变色时,由交警放行车辆行人观察者的run()方法,当灯坏了,由交警委托调用修理工的repair()方法,EvenHandler委托类其实可以看做一个外观(外观模式)。
JAVA实现可以参考:https://blog.csdn.net/gdutxiaoxu/article/details/51824769
来一段神奇的总结:
总结自:《大话设计模式》观察者模式