1、前言java
观察者模式其实最好的名称应该是“发布订阅”模式,和咱们如今大数据之中的发布订阅方式比较相似,可是也有区别的地方,在上一个设计模式,咱们学习了仲裁者模式,其中当控件的状态发生改变的时候就会向仲裁者发出信息,让仲裁者进行仲裁,这其实和发布订阅很是的相似,可是用处是不同的,仲裁者模式是用来解除复杂对象之间的相互调用的关系,从而独立出来进行开发,而观察者模式是在被观察者状态改变的时候被动的被唤醒进行相应的处理,二者的实现比较相似,好比都是被动唤醒的,可是思想和用处是不同的,被唤醒以后的处理是不同的。git
2、代码编程
首先咱们本身实现观察者模式,其次咱们使用java已经实现好的观察者接口,而后来对比一下二者的不一样。设计模式
(一)、本身实现观察者模式dom
package zyr.dp.observer; import java.util.ArrayList; import java.util.Iterator; public abstract class NumberGenerator { private ArrayList observers=new ArrayList(); public void add(Observer observer){ observers.add(observer); } public void remove(Observer observer){ observers.remove(observer); } public void notifyObserver(){ Iterator it=observers.iterator(); while(it.hasNext()){ Observer object=(Observer)it.next(); object.update(this); } } public abstract void execuate(); public abstract int getNumber(); }
package zyr.dp.observer; import java.util.Random; public class RandomNumberGenerator extends NumberGenerator { private Random random=new Random(); private int number; public int getNumber(){ return number; } public void execuate() { for(int i=0;i<20;i++){ number=random.nextInt(60); notifyObserver(); } } }
package zyr.dp.observer; public interface Observer { public abstract void update(NumberGenerator object); }
package zyr.dp.observer; public class DigitalObserver implements Observer { public void update(NumberGenerator object) { System.out.println("DigitalObserver:"+object.getNumber()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
package zyr.dp.observer; public class GraphObserver implements Observer { public void update(NumberGenerator object) { System.out.print("GraphObserver:"); for(int i=0;i<object.getNumber();i++){ System.out.print("*"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(); } }
package zyr.dp.observer; public class Main { public static void main(String[] args) { NumberGenerator numberGenerator=new RandomNumberGenerator(); numberGenerator.add(new DigitalObserver()); numberGenerator.add(new GraphObserver()); numberGenerator.execuate(); } }
由此能够看到当被观察者的状态发生改变的时候会主动通知观察者,使用notifyObserver的方法将本身的状态传递过去,由于是本身定义的被观察者的抽象类以及接口,所以使用起来很是的方便,代码也不是不少,可以按照本身的要求来完成更新操做,对比与仲裁者模式,被观察者是主动将本身的内容传递给观察者的,而仲裁者模式中,组员是自己就已经组合进了仲裁者之中,这也是一点不一样。代码比较简单,这里被观察者使用了抽象类而不使用接口的缘由是须要定义对观察者对象的委托,所以使用了抽象类,而观察者只用了update方法将被观察者经过参数传递的方式委托进来,所以使用接口更加清晰一点,固然抽象类也能够,只不过能使用接口的就不要使用抽象类,由于一个类只能继承一个父类,可是能够实现不少接口。组件化
(二)、使用java自带的观察者模式学习
package zyr.dp.java; import java.util.Observable; import java.util.Random; public class RandomNumberGenerator extends Observable { private Random random=new Random(); private int number; public int getNumber(){ return number; } public void execuate() { for(int i=0;i<20;i++){ number=random.nextInt(60); setChanged(); notifyObservers(); } } }
package zyr.dp.java; import java.util.Observable; import java.util.Observer; public class DigitalObserver implements Observer { public void update(Observable object, Object arg) { System.out.println("DigitalObserver为:"+((RandomNumberGenerator)object).getNumber()); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
package zyr.dp.java; import java.util.Observable; import java.util.Observer; public class GraphObserver implements Observer { public void update(Observable object, Object arg) { System.out.print("GraphObserver为:"); for(int i=0;i<((RandomNumberGenerator)object).getNumber();i++){ System.out.print("*"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(); } }
package zyr.dp.java; import java.util.Observable; public class Main { public static void main(String[] args) { Observable observable=new RandomNumberGenerator(); observable.addObserver(new DigitalObserver()); observable.addObserver(new GraphObserver()); ((RandomNumberGenerator)observable).execuate(); } }
能够看到在java自定义的观察者模式中,首先要修改setChanged();来使notifyObservers生效,其次,传递的参数不是很灵活,须要强制转换成咱们想要的东西,最后在使用的时候也须要强制转换,这是比较麻烦的,而且被观察者也是继承了抽象类Observable,不方便之后功能的扩展,若是之后再想继承其它的类就很麻烦了。咱们本身设计的时候,可使用某些方式把抽象类变成接口,不过也须要必定的操做。大数据
3、总结this
经过观察者模式使得观察者和被观察者之间面向抽象编程,观察者不用知道本身观察的对象究竟是谁的实例,只须要知道这个对象继承了被观察者的抽象类,所以当被观察者增长的时候,观察者能够不用修改。一样的,对于被观察者的实例来讲,并不须要知道本身究竟是呗哪个观察者观察了,只须要知道观察本身的观察者确定使用了观察者的接口,所以观察者和被观察者之间经过面向抽象编程提升了可扩展性,便于组件化。spa
咱们能够看到在面向对象编程中可以使用委托的就不要使用继承,委托是弱关联,继承是强关联。而且将一些共同操做抽象出来放到抽象类之中去定义,在参数传递中不使用具体类型而是用接口或者抽象类,这样的设计思想便于组件化,具备可替代性。