观察者模式 Java
观察者模式(Observer Pattern
)指多个观察者同时依赖于某个主题对象,对象发生改变后会主动通知观察者进行改变的软件设计模式。
主要内容:
- 简要原理
- 观察者模式实例
- 完整工程链接
简要原理
百度百科:
观察者模式
别名:发布(publish
)-订阅(subscribe
)模式、模型(model
)-视图(view
)模式、源-收听者模式、从属者模式
观察者模式有两个主要对象:观察者和被观察者,其中,观察者的功能实现依赖于被观察者(比如,观察者是前端界面,被观察者是后台数据,界面需要利用后台数据进行界面展示),当观察者观察到被观察者的状态发生变化后,自身也随之发生变化(比如,界面显示天气信息,当后台天气数据发生变化后,前端会根据变化的数据重新构建界面)。
实现:并不是观察者时刻关注被观察者是否发生变化,而是被观察者包含有观察者对象,而观察者则具体实现了更新方法,当被观察者自身发生变化后,遍历观察者列表,调用更新方法,通知观察者进行相应的变化(即订阅 - 通知 - 撤销订阅的结构)。
观察者模式实例
参考:
首先定义一个抽象主题,里面实现绑定、撤销、通知观察者的方法,Subject.java
代码如下:
package ObserverModel2;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Lenovo on 2017/5/15.
*/
public abstract class Subject {
private List<Observer> list = new ArrayList<>();
/**
* 订阅
*
* @param observer
*/
public void Attach(Observer observer) {
list.add(observer);
}
/**
* 撤销订阅
*
* @param observer
*/
public void Detach(Observer observer) {
list.remove(observer);
}
/**
* 通知
*/
public void Notify() {
System.out.println("Update:");
for (Observer observer : list) {
observer.Update();
}
}
}
被观察者中包含有一个气候对象(WeatherBean
),其中包含有季节(season
)、天气(weather
),WeatherBean.java
代码如下:
package ObserverModel2;
/**
* Created by Lenovo on 2017/5/15.
*/
public class WeatherBean {
/**
* 季节:春夏秋冬
*/
private String season;
/**
* 天气:冷、热
*/
private String weather;
public WeatherBean(String season, String weather) {
this.season = season;
this.weather = weather;
}
public String getSeason() {
return season;
}
public void setSeason(String season) {
this.season = season;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
@Override
public String toString() {
return "WeatherBean{" +
"season='" + season + '\'' +
", weather='" + weather + '\'' +
'}';
}
}
具体实现被观察者,ConcreteSubject.java
如下:
package ObserverModel2;
/**
* Created by Lenovo on 2017/5/15.
*/
public class ConcreteSubject extends Subject {
private WeatherBean weatherBean;
public ConcreteSubject(WeatherBean weatherBean) {
this.weatherBean = weatherBean;
}
/**
* 设置季节变换和天气变换
*
* @param weatherBean
*/
public void setWeatherBean(WeatherBean weatherBean) {
this.weatherBean = weatherBean;
this.Notify();
}
public WeatherBean getWeatherBean() {
return weatherBean;
}
/**
* 季节变换
*
* @param season
*/
public void setSeason(String season) {
weatherBean.setSeason(season);
this.Notify();
}
/**
* 天气变换
*
* @param weather
*/
public void setWeather(String weather) {
weatherBean.setWeather(weather);
this.Notify();
}
@Override
public String toString() {
return "ConcreteSubject{" +
"weatherBean=" + weatherBean +
'}';
}
}
定义一个接口,包含观察者需要实现的更新方法,以便被观察者统一调用,Observable.java
代码如下:
package ObserverModel2;
/**
* Created by Lenovo on 2017/5/15.
*/
public interface Observable {
/**
* 更新接口
*/
void Update();
}
观察者 Observer.java
代码如下:
package ObserverModel2;
/**
* Created by Lenovo on 2017/5/15.
*/
public class Observer implements Observable {
/**
* 观察者
*/
private String name;
/**
* 具体主题
*/
private ConcreteSubject subject;
public Observer(String name, ConcreteSubject subject) {
this.name = name;
this.subject = subject;
// 绑定观察者
this.subject.Attach(this);
Update();
}
@Override
public void Update() {
String str = String.format("name: %s subject: %s", name, subject.toString());
System.out.println(str);
}
}
测试代码 Test.java
如下:
package ObserverModel2;
/**
* Created by Lenovo on 2017/5/16.
*/
public class Test {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject(new WeatherBean("spring", "warm"));
Observer observer = new Observer("one", subject);
Observer observer1 = new Observer("two", subject);
Observer observer2 = new Observer("three", subject);
// 修改对象
subject.setSeason("summary");
subject.setWeather("hot");
}
}
实现结果:
利用Java自带可观察对象 Observable
参考:
Interface Observer:抽象观察者
Class Observable:可观察对象
Java
自带了抽象主题(Observable
),以及更新接口(Observer
)
修改后具体主题(ConcreteSubject.java
)代码如下:
package ObserverModel3;
import ObserverModel2.WeatherBean;
import java.util.Observable;
/**
* Created by Lenovo on 2017/5/16.
*/
public class ConcreteSubject extends Observable {
private WeatherBean weatherBean;
public ConcreteSubject(WeatherBean weatherBean) {
this.weatherBean = weatherBean;
}
/**
* 设置季节变换和天气变换
*
* @param weatherBean
*/
public void setWeatherBean(WeatherBean weatherBean) {
this.weatherBean = weatherBean;
Notify();
}
public WeatherBean getWeatherBean() {
return weatherBean;
}
/**
* 季节变换
*
* @param season
*/
public void setSeason(String season) {
weatherBean.setSeason(season);
Notify();
}
/**
* 天气变换
*
* @param weather
*/
public void setWeather(String weather) {
weatherBean.setWeather(weather);
Notify();
}
@Override
public String toString() {
return "ConcreteSubject{" +
"weatherBean=" + weatherBean +
'}';
}
private void Notify() {
System.out.println("Update:");
this.setChanged();
this.notifyObservers(weatherBean);
}
}
具体观察者(ConcreteObserver.java
)代码如下:
package ObserverModel3;
import ObserverModel2.WeatherBean;
import java.util.Observable;
import java.util.Observer;
/**
* Created by Lenovo on 2017/5/16.
*/
public class ConcreteObserver implements Observer {
/**
* 观察者
*/
private String name;
/**
* 具体主题
*/
private ConcreteSubject subject;
public ConcreteObserver(String name, ConcreteSubject subject) {
this.name = name;
this.subject = subject;
// 绑定观察者
this.subject.addObserver(this);
this.update(null, null);
}
@Override
public void update(Observable o, Object arg) {
String str = null;
if (arg != null) {
WeatherBean bean = (WeatherBean) arg;
str = String.format("name: %s subject: %s", name, bean.toString());
} else {
str = String.format("name: %s subject: %s", name, subject.toString());
}
System.out.println(str);
}
}
测试代码(Test.java
)如下:
package ObserverModel3;
import ObserverModel2.WeatherBean;
/**
* Created by Lenovo on 2017/5/16.
*/
public class Test {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject(new WeatherBean("spring", "warm"));
ConcreteObserver observer = new ConcreteObserver("one", subject);
ConcreteObserver observer1 = new ConcreteObserver("two", subject);
ConcreteObserver observer2 = new ConcreteObserver("three", subject);
// 修改对象
subject.setSeason("summary");
subject.setWeather("hot");
}
}
完整工程链接
https://git.oschina.net/zjZSTU/observerdemo.git