【笨鸟先飞】Java重新学习日记15--设计模式之观察者模式

设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。设计模式的某一个模式,是用来解决某一种特定场景。当某个对象A的状态发生了变化,而另外的对象B需要根据对象A的变化而跟着变化,当B的对象数量,且处理方式不一致,对象类型不一致的时候,观察者模式是一个好的选择。

观察者模式,分享者A中获取对象B将之放入集合中,当数据发送变化时,运行对象B中的对应方法。

使用时,对象B实现一个接口,分享者A按照接口类来获取对象B,然后放入集合。对象B一定具备对应方法,比如notify 。 分享者A的状态发生变化,就把集合中的每一个对象都运行一次notify方法。从而达到A的一旦变化,就能够导致B的联动。

那么该模式是为了解决什么样的问题一步步演化出来的?

回到应用场景:当某个对象A的状态发生了变化,而另外的对象B需要根据对象A的变化而跟着变化。

根据描述采用组合的概念,A状态变化时,直接调用一下B的方法,就可以实现。这个是基础场景,就是A去调用B

如果,B不只一个。则在A状态变化的方法中,去调用BCD的各种对应的方法。这个也是很常见,但是如果BCD的调用是因为相同的目的呢?

正常顺序是A的变化,导致BCD三个对象的联动变化。比如:A点个菜,则B老板收钱,C厨师炒菜,D小二倒茶打饭。

但如果BCD是同样目的的变化。比如,A写黑板,BCD做笔记。

那就变成,BCD是使用相同的方法,仍然是A的变化去调用BCD的方法。

这里就可以引入观察者模式的一个部分,这个思路源于工厂模式。BCD相同被A调用的方法,通过接口来实现。这样BCD就可以通过一个集合装到一起,在A中通过遍历该集合来实现方法的调用。

比如,A写黑板,BCDEFG做笔记。

我们定义一个接口,里面是抽象的做笔记方法。

这里BCDEFGimplement了该接口,也实现了该记笔记方法。而且,BCDEFG是不同的类的话,实现的笔记方法的具体内容很可能是完全不同的。

比如当A是一个牛逼老师时,BCDEFG就可以是完全不同的类,如,学生,听课的家长,坐后排的校长,摄像师,外来考察的教授,教育集团老总等。

这里的应用场景就有了一些变化:当某个对象A的状态发生了变化,而另外多个BCDEF需要根据对象A的某个相同的特征点的变化而跟着变化。

我们已经实现了BCDEF跟随A而变化的,这说明,我们已经学会这个模式了?不是,以上是观察者模式的一部分,用来解决相关场景的简单场景。

现在我们继续之前的假设,A是一个牛逼老师,正在讲课。下方有BCDEFG,在听课,其中学生有50个在听课,家长有30个,校长有1个,摄影师有1个,外来考察的教授2个,教育集团老总1个。

这里我们仍可以使用之前的集合将这些包含在里面。现在代码已经固定。如果,后面又有一个教务处主任来听课呢?

是的我们的代码还有提升空间,这个空间包括两部分:

1:在增加和减少BCDEF的时候,能否不修改A的代码?

2BCDEF自己进行增加和减少的时候,是否可以不干扰其他对象。

观察者模式为我们解决了这个问题,在A中实现三个标准方法:

Register/addunRegister/removenotify

Register是给其他模块调用的,其他模块将自己传入A的以接口为类来接收。

然后将对象存入集合中。

unRegister也是给其他模块调用,是其他模块将自己从A的集合中删去。

notify 则是A遍历其集合,来调用接口的方法。

以上,在BCDEF中,自己使用RegisterunRegister来确认自己是否关注A的行为。

A一旦发生变化则会启用notify来是关注A行为的所有对象都分别进行自己对应的操作。

成功的实现了解耦,任何一个新增对象,新增类,只需要获取到A的对象和实现接口,就可以对对象A进行关注。

典型案例,android的事件响应机制。平时所见的listener就是观察者模式的一个官方应用。Onclicklistener就是任何一个组件都可以注册该listener,注册后,该组件就被关注,一点该组件的状态发生变化(被点击),就会触发onclick方法。

使用时通过实现Onclicklistener接口。通过setOnclicklistener来传入实现Onclicklistener接口的对象,当被点击时,实现的接口内容就会被触发。

以上,就是观察者模式。

猜你喜欢

转载自blog.csdn.net/dax120/article/details/78963346