注:源碼及見解參見慕課網
第一節
1.官方定義:
定義對象間的一種一對多的依賴關系。當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新
2.觀察者模式的結構:
Subject | Observer |
---|---|
+Attach(o:Observer) | +Update( ) |
+Detach(o:Observer) | |
+Notify( ) |
3.標準模板
Subject.java
import java.util.ArrayList;
import java.util.List;
public class Subject {
//保護注冊的觀察者對象
private List observers = new ArrayList();
public void attath(Observer observer){
observers.add(observer);
}
public void detach(Observer observer){
observers.remove(observer);
}
protected void notifyObservers(){
for(Observer observer:observers){
observer.update(this);
}
}
}
Observer.java
public interface Observer {
public void update(Subject subject);
}
ConcreteSubject.java
public class ConcreteSubject extends Subject {
/*目標對象的狀態*/
private String subjectState;
public String getSubjectState() {
return subjectState;
}
/*通知觀察者*/
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
this.notifyObservers();
}
}
ConcreteObserver.java
public class ConcreteObserver implements Observer {
/*觀察者的狀態*/
private String observerState;
public void update(Subject subject) {
observerState = ((ConcreteSubject)subject).getSubjectState();
}
}
4.實例
weather.java
import java.util.ArrayList;
import java.util.List;
public class Weather {
//創建觀察者列表
private List people = new ArrayList();
//添加觀察者
public void attath(People people){
this.people.add(people);
}
//刪除觀察者
public void detach(People people){
this.people.remove(people);
}
//通知觀察者更新
protected void updata(){
for(Peoplehuman:people){
human.updata(this);
}
}
}
TodayWeather.java
public class ConcreteObserver implements Observer {
//觀察者的狀態
private String observerState;
public void update(Subject subject) {
observerState = ((ConcreteSubject)subject).getSubjectState();
}
}
People.java
public interface People {
//創建更新的接口
public void updata(Weather weather);
}
ConcretePeople.java
public classConcretePeople implements People{
private String infromation;
private String name;
private String talk;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTalk() {
return talk;
}
public void setTalk(String talk) {
this.talk = talk;
}
@Override
public void updata(Weather weather) {
infromation = ((TodayWeather)weather).getWeatherContext();
System.out.println(name+"說:今天"+infromation+talk);
}
}
Test.java
public class Test {
public static void main(String[] args) {
ConcretePeople man = new ConcretePeople();
man.setName("小強");
man.setTalk("以該出去踢球");
ConcretePeople woman = new ConcretePeople();
woman.setName("小紅");
woman.setTalk("應該去逛街");
TodayWeather todayWeather = new TodayWeather();
todayWeather.setWeatherContext("天氣晴朗,藍天白云,沒有霧霾?。?);
man.updata(todayWeather);
woman.updata(todayWeather);
}
}
輸出結果:
小強說:今天天氣晴朗,藍天白云,沒有霧霾??!以該出去踢球
小紅說:今天天氣晴朗,藍天白云,沒有霧霾??!應該去逛街
第二節
上一節里,我書寫了觀察者模式的模板和例子,
這一次我要再次深入的介紹觀察者模式的兩種方式和java自己封裝好的觀察者結構。
1.實現的兩種方式:
推模型和拉模型
推模型:目標對象主動向觀察者推送目標的詳細信息,推送的信息通常是目標對象的全部或部分數據。
拉模型:目標對象在通知觀察者的時候,只傳遞少量信息。
如果觀察者需要更具體的信息,由觀察者主動到目標對象中獲取,相當于是觀察者從目標對象中拉數據。
一般這種模型的實現中,會把目標對象自身通過update方法傳遞給觀察者。
對于拉模型,上次一文中介紹的模板和例子均是采用的拉模型。下面我為大家修改上次的例子變成推模型。
Weather.java
import java.util.ArrayList;
import java.util.List;
public class Weather {
//創建觀察者列表
private List people = new ArrayList();
//添加觀察者
public void attath(People people){
this.people.add(people);
}
//刪除觀察者
public void detach(People people){
this.people.remove(people);
}
//通知觀察者更新
protected void updata(String content){
for(Peoplehuman:people){
human.updata(content);
}
}
}
TodayWeather.java
public class TodayWeather extends Weather{
//今日天氣
private String weatherContext;
public String getWeatherContext**() {
return weatherContext;
}
public void setWeatherContext(String weatherContext) {
this.weatherContext = weatherContext;
this.updata(weatherContext);
}
People.java
public interface People {
//創建更新的接口
public void updata(String content);
}
ConcreteWeather.java
public class ConcretePeople implements People{
private String infromation;
private String name;
private String talk;
public String getName() {
return name;
}
public void setName**(String name) {
this.name = name;
}
public String getTalk() {
return talk;
}
public void setTalk(String talk) {
this.talk = talk;
}
@Override
public void updata(String content) {
infromation = content;
System.out.println(name+"說:今天"+infromation+talk);
}
}
Test.java
public class Test {
public static void main(String[] args) {
ConcretePeople man = new ConcretePeople();
man.setName("小強");
man.setTalk("以該出去踢球");
ConcretePeople woman = new ConcretePeople();
woman.setName("小紅");
woman.setTalk("應該去逛街");
TodayWeather todayWeather = new TodayWeather();
todayWeather.setWeatherContext("天氣晴朗,藍天白云,沒有霧霾??!");
man.updata(todayWeather.getWeatherContext());
woman.updata(todayWeather.getWeatherContext());
}
}
輸出結果:
小強說:今天天氣晴朗,藍天白云,沒有霧霾??!以該出去踢球
小紅說:今天天氣晴朗,藍天白云,沒有霧霾!!應該去逛街
2.推拉模型的比較
Weather.java?
import java.util.Observable;
public class Weather extends Observable{
private String WeatherContent;
public String getWeatherContent() {
return WeatherContent;
}
public void setWeatherContent(String weatherContent) {
WeatherContent = weatherContent;
//下面這句話在調用java里的Observer時必不可少
this.setChanged();
//這是拉模型沒有參數
this.notifyObservers();
//這是推模型帶參數
this.notifyObservers(weatherContent);
}
}
?People.java
import java.util.Observable;
public class Weather extends Observable{
private String WeatherContent;
public String getWeatherContent() {
return WeatherContent;
}
public void setWeatherContent(String weatherContent) {
WeatherContent = weatherContent;
//下面這句話在調用java里的Observer時必不可少
this.setChanged();
//這是拉模型沒有參數
this.notifyObservers();
//這是推模型帶參數
this.notifyObservers(weatherContent);
}
}
?Test.java
public class Test {
public static void main(String[] args) {
Weather weather = new Weather();
weather.setWeatherContent("今天天氣晴朗,藍天白云??!");
People man = new People();
man.setName("小明");
man.setTalk("我去踢球");
People woman = new People();
woman.setName("小紅");
woman.setTalk("我要逛街");
man.update(weather, weather.getWeatherContent());
woman.update(weather, weather.getWeatherContent());
}
}
輸出結果:
小明說:今天天氣晴朗,藍天白云!!,我去踢球推模式
小明說:今天天氣晴朗,藍天白云!!,我去踢球拉模式
小紅說:今天天氣晴朗,藍天白云??!,我要逛街推模式
小紅說:今天天氣晴朗,藍天白云??!,我要逛街拉模式
第三節
1.區別對待觀察者場景問題:
最后一個問題,就是判斷性的添加觀察者。實現方法很簡單,將subject這個類中的notifyChange()這個方法讓其不去實現,使其在他的派生類中實現,(這樣我們不妨把subject這個類作為抽象類,然后將notufyChange()這個方法作為抽象方法讓其在子類中實現方法)然后就是在concretesubject()中在notifyChange()來判斷那個對象可以做更新。(注:這里的方法名均為第一篇文章中模板的名字,和下面的例子不同)。
Weather.java
import java.util.ArrayList;
import java.util.List;
public abstract class Weather {
public List People humans = new ArrayListPeople();
public void attach(People people){
humans.add(people);
}
public void detach(People people){
humans.remove(people);
}
public abstract void notifyWeather();
}
Today.java
public class Today extends Weather{
private String weatherContent;
public void notifyWeather() {
for(People human:humans){
if(weatherContent.equals("下雨")){
if(human.getPeopleName().equals("小紅")){
human.updata(this);
}
}
if(weatherContent.equals("下雪")){
if(human.getPeopleName().equals("小明")){
human.updata(this);
}
}
}
}
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
this.notifyWeather();
}
}
People.java
public interface People {
public void updata(Weather weather);
public void setPeopleName(String name);
public String getPeopleName();
}
Human.java
public class Human *implements People{
private String name;
public String getTalk() {
return talk;
}
public void setTalk(String talk) {
this.talk = talk;
}
public String getWeatherContent() {
return weatherContent;
}
private String talk;
private String weatherContent;
@Override
public void updata(Weather weather) {
System.out.println(name+"說:"+((Today)weather).getWeatherContent()+talk);
}
@Override
public void setPeopleName(String name) {
this.name = name;
}
@Override
public String getPeopleName**() {
return this.name;
}
}
Test.java
public class Test {
public static void main(String[] args) {
Today today = new Today();
Human man = new Human();
man.setPeopleName("小明");
man.setTalk("我要看雪");
Human woman = new Human();
woman.setPeopleName("小紅");
woman.setTalk("下雨了不去了");
today.attach(man);
today.attach(woman);
today.setWeatherContent("下雪");
}
}
輸出結果:
小明說:下雪我要看雪