JDK Observer设计模式研究
当前位置:以往代写 > JAVA 教程 >JDK Observer设计模式研究
2019-06-14

JDK Observer设计模式研究

JDK Observer设计模式研究

副标题#e#

今朝设计模式的先容性文章越来越多,但设计模式的研究性文章仍然较量欠缺,这着实让人以为有点遗憾。本文旨在抛砖引玉,详细阐明一下java中jdk自带的observer设计模式(下文如没出格指出,observer设计模式就意指java中jdk自带的observer设计模式)的实现。

1.Observer设计模式提要

Observer设计模式在GOF里属于行为设计模式。JDK里提供的observer设计模式的实现由java.util.Observable类和java.util.Observer接口构成。从名字上可以清楚的看出两者在Observer 设计模式中别离饰演的脚色:Observer是调查者脚色,Observable是被调查方针(subject)脚色。

Observable是一个封装subject根基成果的类,好比注册observer(attach成果),注销observer(detatch成果)等。这些成果是任何一个饰演observerable脚色的类都需要实现的,从这一点上来讲,JDK里将这些通用成果专门封装在一个类里,显得合情公道。凡是环境下,我们的类只要从Observerable类派生就可以称为observerable脚色类,利用很是简朴。

2.利用observer设计模式存在的坚苦

但我们不得不留意到,在项目实际开拓傍边,环境往往要巨大得多。java不支持多担任特性在许多时候是阻碍我们利用observer设计模式的绊脚石。好比说,我们设计的一个类已经是某个类的派生类,在这种环境下同时想让它饰演observerable脚色将变得贫苦。如何实现“多担任”的结果是摆在我们眼前的一浩劫题。下面我们首先阐明一下Observable类。

3.Observable类“触发通知”的道理

Observable必需“有变革”才气触发通知observer这一任务,这是它的本质浮现。查察源码便可知一二。Observerable部门源码如下:

//……省略……
   private boolean changed = false;
   //……省略……
   public void notifyObservers(Object arg) {
   //……省略……
     Object[] arrLocal;
     synchronized (this) {
      //……省略……
      if (!changed)
       return;
       arrLocal = obs.toArray();
       clearChanged();
     }
   //……省略……
   protected synchronized void setChanged() {
    changed = true;
   }

   protected synchronized void clearChanged() {
    changed = false;
   }

正如粗的斜体标注部门所示,在notifyObservers(Object arg) 要领里if (!changed) return;语句汇报我们,若changed属性值为false,将直接返回,基础不会触发通知操纵。而且我们留意到changed 属性被初始化为false,这将意味着假如我们不主动配置changed属性为true,将不会有任何变革,也就是说基础起不到“通知”浸染。因此,配置changed属性的值是我们应用jdk observer 设计模式的要害地址。那么如何才气配置changed属性呢?从源码可以看出,独一的进口是通过setChanged()。下面我们阐明一下changed属性及相关的要领setChanged()和clearChanged()。

4.Observable类的阐明

Observable#changed属性的初始值为false,这很容易领略,不再具体告诉。细心的读者大概会留意到跟changed属性有关的两个要领setChanged()和clearChanged(),它们的修饰符都是protected。想强调的是,是protected,而不是public。但这样是否有其须要性和公道性?谜底是必定的。在前面的阐明中,我已经提到,setChanged()要领是配置changed的独一进口,它的修饰符界说为protected,就意味着通过界说Observable的工具,再配置changed属性将变得不行能。从这个意义上说,要想应用observer设计模式,必需担任Observable类方可。关于这一点,下文还会提及。可是,为什么不能界说成public?这好像难以领略。因为界说成public,我们不就可以很利便地配置changed属性的值吗?为了弄清楚这个问题,我们照旧看一下Observable里的相关的代码:

//……省略……
   public void notifyObservers(Object arg) {
   //……省略……
    for (int i = arrLocal.length-1; i>=0; i--)
     ((Observer)arrLocal[i]).update(this, arg);
   }
    

 

这段代码表达的意思是说找出所有已注册的Observer,再逐个举办“通知”,通过挪用Observer#update(Observable,Object)要领举办通知。我们看到,update 第一个参数是this,我们同时还必需留意到,这段代码是Observable类里的代码。这就相当于是在一再强调,发出“通知”的,必需是observable本身(Observable类可能其派生类),其它任何类都不可。这就意味着我们的observable类担任Observable类是须要的,因为假如不担任,而回收组合的话,将无法担保能通报好this。换句话说,回收组合的方法利用Observable类,将变得险些没有任何意义。同时,修饰符界说为protected,可以确保是在Obsrvable里举办触发通知的,不会在其它任那里所举办通知,这显得内敛性很强。假如将setChanged()修饰符界说为public,将无法担保正确“通报this”的硬性要求,这不切合“只有observalbe才气直接或间接通知observer”这一observable设计模式的硬性要求。由此我们可见一斑,jdk的许多理念的思想性是何等的强。


#p#副标题#e#

5.办理利用observer设计模式存在的坚苦

#p#分页标题#e#

借助adapter设计模式(详见本人颁发的adapter设计模式相关文章)和java支持多接口特性根基可以办理“多担任”问题。根基思想是团结担任/实现和组合来到达结果。在上面的阐明中,我们已经知道,Observable类必需担任利用,不能组合利用,因此我们只需要将需饰演成observerable脚色的类装扮成adapter脚色,将该类原担任的类装扮成adaptee脚色即可。示例代码如下:

//欲充当observable脚色的类的本来的代码:
   public class MyObject extends BaseObject {
    public MyObject() {
     public void method1(){}
    }
   }
   //充当observable脚色后的代码:
   public class MyObject extends Observable {
    private BaseObject baseObject = null;
     public MyObject(BaseObject baseObject) {
      this.baseObject = baseObject;
     }
   }

6.留意事项:

假如上例中的BaseObject也用到需要通报“this”的要领,那么上面的组合利用要领将有大概失效。这种环境是最糟糕的环境。此时可以思量在BaseObject类这些“瓶颈”处所只管回收接口取代类(包罗抽象类)来办理。

    关键字:

在线提交作业