<!-- 设计模式 -->
<!--是一套被反复使用、多数人知
晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了
可重用代码、让代码更容易被他人理解、保证代 码可靠性 -->
-------------------------------------------------------------
<!-- 观察者模式 observer patterns-->
<!-- 对于天气预报的举例,首先这是常规的方法 -->
public class WeatherData { private int low; private int height; private String weather; public int getLow() { return low; } public int getHeight() { return height; } public String getWeather() { return weather; } public void setData(int low,int height,String weather){ this.low = low; this.height = height; this.weather = weather; change(); } private void change() { Xiaomi xiaomi = new Xiaomi(); xiaomi.disPlay(getLow(),getHeight(),getWeather()); Chuizi chuizi = new Chuizi(); chuizi.disPlay(getLow(),getHeight(),getWeather()); } }
public class Xiaomi { public void disPlay(int low, int height, String weather) { System.out.println(low + ":" + height + ":" + weather); } }
public class Chuizi { public void disPlay(int low, int height, String weather) { System.out.println(low + ":" + height + ":" + weather); } }
但是这是有问题的,不够灵活,有的厂商想加上这个功能,有的厂商想去掉这个功能
就像报纸
出版社的任务就是出报纸
你订阅了出版社的报纸,出版社就会将新的报纸给你送
你不需要该出版社的报纸,可以取消订阅
只要出版社还在,就会一直有很多人取消或订阅报纸
观察者模式
定义了对象间一对多的依赖,这样一来,当一个对象的状态改变时,
它的所有依赖都会自动收到通知并自动更新
报社是主题,订阅者是观察者对象
/*定义一个主题接口*/ public interface Subject { public void addObserver(Observer observer); public void removeObserver(Observer observer); public void notifyObserver(); }
/*主题要继承自主题接口,用于添加一些对观察者操作的几个方法*/ public class WeatherData implements Subject{ private int low; private int height; private String weather; //定义一个list,用于存放所有观察者,方便下面进行通知 private List<Observer> list = new ArrayList<Observer>(); public int getLow() { return low; } public int getHeight() { return height; } public String getWeather() { return weather; } public void setData(int low,int height,String weather){ this.low = low; this.height = height; this.weather = weather; //通知观察者 notifyObserver(); } //对观察者进行添加 @Override public void addObserver(Observer observer) { if(observer == null){ return; } if(!list.contains(observer)){ list.add(observer); } } //通知所有观察者 @Override public void notifyObserver() { for(Observer o : list){ o.update(getLow(), getHeight(), getWeather()); } } //删除观察者 @Override public void removeObserver(Observer observer) { list.remove(observer); } }
/*定义一个观察者接口,观察者在继承之后要实现他的方法用于更新数据*/ public interface Observer { public void update(int low,int height,String weather); }
public class Xiaomi implements Observer{ /** * 对于观察者,我希望做到不管是添加该业务还是取消,主题端是不管的,所以 * 定义构造方法,new出来这个对象的时候自动加入到被通知列(成为观察者), * 同时还设有取消该业务 */ private Subject subject; public Xiaomi(Subject subject){ this.subject = subject; subject.addObserver(this); } public void cancle(){ subject.removeObserver(this); } public void disPlay(int low, int height, String weather) { System.out.println(low + ":" + height + ":" + weather); } @Override public void update(int low, int height, String weather) { disPlay(low,height,weather); } }
public class Chuizi implements Observer{ private Subject subject; public Chuizi(Subject subject){ this.subject = subject; subject.addObserver(this); } public void cancle(){ subject.removeObserver(this); } public void disPlay(int low, int height, String weather) { System.out.println(low + ":" + height + ":" + weather); } @Override public void update(int low, int height, String weather) { disPlay(low,height,weather); } }
测试运行
public class test { public static void main(String[] args) { WeatherData data = new WeatherData(); <!-- 加入该业务 --> Xiaomi xiaomi = new Xiaomi(data); Chuizi chuizi = new Chuizi(data); <!-- 两个都通知 --> data.setData(1, 10, "晴朗"); <!-- 取消该业务 --> xiaomi.cancle(); <!-- 只通知一个 --> data.setData(2, 12, "晴朗"); } }
======================================================================
======================================================================
======================================================================
java中内置的观察者模式
在这里不是实现了而是继承
public class WeatherData extends Observable { private int low; private int height; private String weather; public int getLow() { return low; } public int getHeight() { return height; } public String getWeather() { return weather; } public void setData(int low,int height,String weather) { this.low = low; this.height = height; this.weather = weather; change(); } public void change() { /*Observable,可以点击进入Observable看里面的方法,首先setChanged()将changed属性改为true 代表有改变*/ setChanged(); /* 通知观察者 */ <!-- 方式1 --> notifyObservers(); <!-- 方式2 --> notifyObservers(new Object[]{getLow(),getHeight(),getWeather()}); } }
import java.util.Observable; import java.util.Observer; public class Htc implements Observer{ /*构造方法,将自己加入通知列*/ private Observable observable; public Htc(Observable observable) { this.observable = observable; observable.addObserver(this); } /*取消该业务 */ public void cancel() { observable.deleteObserver(this); } public void display(int low,int height,String weather) { System.out.println("HTC 最低温度:" + low + " 最高温度:" + height + " 天气:" + weather); } @Override public void update(Observable o, Object arg) { /* 拉模式:当要使用的时候再获取 对应上面的方式1 当创建weatherdata的时候会执行父类的构造方法 这个o是从父类中 传过来的(传的是this),所以这个o指的是weatherdata本身,强制转换*/ WeatherData wd = (WeatherData) o; display(wd.getLow(), wd.getHeight(), wd.getWeather()); /* 推模式:不管你用不用,我先给你 对应上面的方式2 当使用notifyObservers(new Object[]{getLow(),getHeight(),getWeather()}); arg不为null*/ if(arg != null) { Object[] array = (Object[]) arg; display(Integer.parseInt(array[0].toString()), Integer.parseInt(array[1].toString()), array[2].toString()); } } }
测试
public class Test { public static void main(String[] args) { WeatherData wd = new WeatherData(); Htc htc = new Htc(wd); wd.setData(2, 8, "晴天"); } }
----------------------------------------------------------------------
----------------------------------------------------------------------
对于要使用自己写的还是java内置的?
java中的主题是要继承的而不是实现的,所以当他已经有了父类的时候就不能再继承其他类
Observable是一个类,主题类只能继承该类,如果主题类已经有
了父类,则无法完成观察者模式,因为Java不支持多继承。
关于观察者模式
该模式定义了对象之间一对多的关系
主题用一个共同的接口来更新观察者
主题和观察者之间用松耦合的方式结合,主题不知道观察者的细节,只知道观察者实现了观察者接口
java中内置了观察者模式
知道使用Java中内置观察者模式的缺点
如有必要,尽量自己实现观察者模式,而不是使用Java中内置的