观察者模式(Java 版)

注:源码及见解参见慕课网

第一节

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("下雪");
  }
}

输出结果:
小明说:下雪我要看雪


你可能感兴趣的:(观察者模式(Java 版))