观察者模式(Java 版)

作者: 绿城河 | 来源:发表于2016-03-13 16:26 被阅读235次
    注:源码及见解参见慕课网
    

    第一节

    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 版)

        本文链接:https://www.haomeiwen.com/subject/wptflttx.html