什么时候需要观察者
答案是需要观察的时候(别喷我),观察的意思就是去看,看外界的状态,外界如果发生了某种变化,那观察外界的对象就执行其对应的操作,这种场景在现实应用中很常见,或者说整个社会就是在我观察你,你观察我这种机制下运行的。实际一点的例子:图形用户程序中,图形对象需要监视后台数据对象的变化来做响应的显示;再举一现在系统中常用的一个服务:短信推送服务,当用户发出了交易请求时,就给该用户发送一个短信验证码。
观察者模式
思考:为了实现观察者对外界对象变化做出响应,我们应该想到两种做法,一种是观察者以轮询的方式观察某一对象,当本次观察发现对象状态发生改变时就做出响应(这种效率太低,因为这意味着观察者在外界对象变化前不能做其他的事情);第二种做法是异步通知的方式,当对象状态发生改变时,对象会向观察者发送消息(在代码中体现为它调用了观察者的某一方法),因为这不像进程间通信一样可以通过中断或者信号的方式实现,对象之间的异步通信只能通过调用彼此之间的方法。这意味着什么?这意味着外界对象必须拥有观察者的指针或者引用。即他们之间应该有聚合关系。
下面我们给出一个简单的实例代码,就以父母来观察孩子为场景
首先给出一个ChinaParent类的实现
- //观察者
- public class ChinaParent {
- //孩子生病了他们会给孩子电话慰问
- public void callChildren(){
- System.out.println("回来吧,带你去看医生");
- }
- }
然后给出Children类的实现
- //被观察者
- public class ChinaChildren {
- private ChinaParent p;
- public void gotSick(){
- p.callChildren();
- }
- }
但是这种观察者的实现方式很不好,因为我们在具体的实现类之间建立的很强的关联关系,我们需要对他们进行解耦,而面向对象中解耦的方法最好不过的是面向接口的设计方法了,所以我们给这两个对象都实现某一接口
- public interface Parent {
- public void callChildren();
- }
- public interface Children {
- public void notifyParent();
- }
- //观察者
- public class ChinaParent implements Parent{
- //孩子生病了他们会给孩子电话慰问
- public void callChildren(){
- System.out.println("回来吧,带你去看医生");
- }
- }
- <pre code_snippet_id="267314" snippet_file_name="blog_20140331_6_1751525" name="code" class="java">//被观察者
- public class ChinaChildren implements Children{
- private Parent p;
- public void notifyParent() {
- p.callChildren();
- }
- public void setObserver(Parent p){
- this.p = p;
- }
- }</pre><br>
- <br>
- <pre></pre>
- 这样就把孩子和具体的Parent解耦了,现在当有新类型的Parent时,我们也不用担心为了将新的观察者加入到我们的系统中而修改源码了。如:
- //观察者
- public class AmericaParent implements Parent{
- //孩子生病了他们会给孩子电话慰问
- public void callChildren(){
- System.out.println("自己去看医生");
- }
- }
首先我们改变Children接口
- public interface Children {
- public void notifyAllParents();
- }
- import java.util.ArrayList;
- //被观察者
- public class ChinaChildren implements Children{
- private ArrayList<Parent> ps;
- public void notifyAllParents() {
- for(int i=0;i<ps.size();i++){
- ps.get(i).callChildren();
- }
- }
- public void addObserver(Parent p){
- ps.add(p);
- }
- public void delObserver(Parent p){
- ps.remove(p);
- }
- }