美高梅网址注册-澳门mgm4858集团登录网址
做最好的网站
来自 澳门mgm4858集团登录网址 2019-10-06 06:01 的文章
当前位置: 美高梅网址注册 > 澳门mgm4858集团登录网址 > 正文

当一个对象改变状态时,就可以使用观察者模式

观察者模式定义了对象之间的一对多关系,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

有一个模式可以帮助你的对象知悉现况,不会错过该对象感兴趣的事,对象甚至在运行时可以决定是否要继续被通知,如果一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式 。观察者模式也是JDK中使用最多的一个设计模式,而我们本章讨论的就是它。

有一个模式可以帮助你的对象知悉现况,不会错过该对象感兴趣的事,对象甚至在运行时可以决定是否要继续被通知,如果一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式 。观察者模式也是JDK中使用最多的一个设计模式,而我们本章讨论的就是它。

模拟现实中的一种需求

  • 报社出版了人民日报,
    1. AB都在报社订阅了人民日报
    2. 这个时候C也想订一份人民日报,报社说那好,你交钱我就给你订上,以后我每期人民日报你都可以收到,C交了钱,订了报纸。
    3. 以后每天ABC都会在门口拿到一份人民日报。
    4. 后来B觉得看报纸没什么意思,就跟报社说不想订了,你把钱退给我吧,报社说行,钱退给你,订阅名单里边就没有你了,以后就不给你报纸了。
    5. 只要报社正常经营,会有越来越多的ABC。

那么首先,我们先来看一看此模式的定义:

那么首先,我们先来看一看此模式的定义:

实现方法

  • 开始时A、B订阅了报纸,代码大概是这样
public class 报社 { String 报纸; //报社本身属性。。。。 //假设每次新出报纸会调用这个方法 public void onPublic(){ a.门口拿包装纸; b.门口拿包装纸; }}public class A { public void 门口拿报纸(String 报纸){ System.out.println; }}public class B { public void 门口拿报纸(String 报纸){ System.out.println("看娱乐新闻!!!"); }}
  • C也想看报纸,所以接着写
public class 报社 { String 报纸; //报社本身属性。。。。 //假设每次新出报纸会调用这个方法 public void onPublic(){ a.门口拿包装纸; b.门口拿包装纸; c.门口拿包装纸; }}public class C { public void 门口拿报纸(String 报纸){ System.out.println("看新发地菜价!!"); }}
  • B又不想订报纸了,那就把B注释掉
public class 报社 { String 报纸; //报社本身属性。。。。 //假设每次新出报纸会调用这个方法 public void onPublic(){ a.门口拿包装纸; //b.门口拿包装纸; c.门口拿包装纸; }}
  • 当ABC越来越多的时候代码就会成了这样
public class 报社 { String 报纸; //报社本身属性。。。。 //每次新出报纸会调用这个方法 public void onPublic(){ a.门口拿包装纸;// b.门口拿包装纸; c.门口拿包装纸; d.门口拿包装纸; e.门口拿包装纸;// f.门口拿包装纸; g.门口拿包装纸; h.门口拿包装纸;// i.门口拿包装纸; j.门口拿包装纸; k.门口拿包装纸; ... }}
  • 所以,正如你看到的
    1. 对于每一个想订阅报纸的人,我们都要修改代码
    2. 无法在运行的时候动态的增加或者删除观察者
    3. 针对的是具体实现编程,并不是针对接口编程
    4. 没有封装改变的部分

OK,报社改个名称叫Observable,ABC改个名称叫Observer,知道怎么订报纸就知道什么是观察者模式了。

明确三个关键词,Observable、subscribe、Observer。Observable是一个有各种状态的对象,Observersubscribe了Observable

那就用观察者模式来实现一下上面的需求,实现观察者模式的方法不止一种,最常见的就是实现Observabe和Observer接口,下面具体实现,对比看一下优点。

                 定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统

                 定义:观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统

观察者模式接口实现

  • Observable
public interface Observable { void registerObserver(Observer o); void removeObserver(Observer o); //更新状态的时候会掉用这个方法 void notifyObserver();}
  • Observer
public interface Observer { void 门口看报纸(String 报纸);}
  • 接下来让报社这个类实现Observable接口,ABC实现Observer接口
public class 报社 implements Observable { private List<Observer> observers; String 报纸; public 报社() { observers = new ArrayList<>(); } @Override public void notifyObserver() { for(Observer o:observers){ o.门口看报纸; } } @Override public void registerObserver(Observer o) { observers.add; } @Override public void removeObserver(Observer o) { int index = observers.indexOf; if(index>0){ observers.remove; } }}

public class A implements Observer{ @Override public void 门口看报纸(String 报纸) { System.out.println; }}
  • 接下来就是订报纸
public class Test { public static void main(String[] args) { 报社 test = new 报社(); A a =new A(); B b = new B(); //a 添加订阅 test.registerObserver; //b 添加订阅 test.registerObserver; //c 添加订阅 test.registerObserver; //b 移除订阅 test.removeObserver; }}
  • 所以,正如你看到的
    1. 对于每一个想订阅报纸的人,我们不需要修改代码,只要实现了Observer接口后registerObserver就好了。
    2. <del>无法</del><mark>随意</mark>在运行的时候动态的增加或者删除观察者
    3. 针对的是<del>具体实现</del><mark>接口</mark>编程,并不是针对<del>接口</del><mark>具体实现</mark>编程
    4. <del>没有</del>封装改变的部分

接下来请LZ用一个例子展出今天的内容:

接下来请LZ用一个例子展出今天的内容:

结束语

观察者模式在JDK就有实现,只不过是用类实现的,需要继承,众所周知,java是单继承的,所以有一定的黑暗面。另外,Java swing 中的JButton、Android中给Button设置OnClickListenner以及现在非常火的RxJava都是观察者模式的实现,有兴趣的可以看看源码,OK就到这里了,欢迎指正。

ex:有这样一个需求,刘能订阅了报刊的报纸,以后每周只要有新报纸发布,刘能就能得到报纸,而刘能也可以选择退订,这时将不再得到报纸。报刊(Newspapers) ,订阅者刘能(Subscriber)。

ex:有这样一个需求,刘能订阅了报刊的报纸,以后每周只要有新报纸发布,刘能就能得到报纸,而刘能也可以选择退订,这时将不再得到报纸。报刊(Newspapers) ,订阅者刘能(Subscriber)。

我们来分析一下,首先,订阅者可以订阅报刊,也可以退订,所以我们需要写两个方法,分别为 registerObserver(订阅) ,removeObserver(退订),我们用一个list来存订阅者,

我们来分析一下,首先,订阅者可以订阅报刊,也可以退订,所以我们需要写两个方法,分别为 registerObserver(订阅) ,removeObserver(退订),我们用一个list来存订阅者,

public class Newspapers {//报刊
    private List<Subscriber> subscriber = new ArrayList<Subscriber>();
    private String paper;

    public void registerObserver(Subscriber subs){//订阅
        subscriber.add(subs);
    }

    public void removeObserver(Subscriber subs){//退订
            subscriber.remove(subs);

    }

    public void setPaper(String paper){//这里控制新出报纸
        this.paper = paper;
        measurementsChanged();//一旦有新报纸出现调用此方法
    }

    public void measurementsChanged(){
        subscriber.get(0).update(paper);
    }
}
public class Newspapers {//报刊
    private List<Subscriber> subscriber = new ArrayList<Subscriber>();
    private String paper;

    public void registerObserver(Subscriber subs){//订阅
        subscriber.add(subs);
    }

    public void removeObserver(Subscriber subs){//退订
            subscriber.remove(subs);

    }

    public void setPaper(String paper){//这里控制新出报纸
        this.paper = paper;
        measurementsChanged();//一旦有新报纸出现调用此方法
    }

    public void measurementsChanged(){
        subscriber.get(0).update(paper);
    }
}

 

 

 

 

在订阅者中,我们设计成只订阅不退订,我们需要一个Newspapers对象,用来订阅,

在订阅者中,我们设计成只订阅不退订,我们需要一个Newspapers对象,用来订阅,

class Subscriber{//订阅者刘能
    private String paper;
    private Newspapers newspapers;
    public Subscriber(Newspapers newspapers) {
        this.newspapers = newspapers;
        newspapers.registerObserver(this);
    }
    public void update(String paper){
        this.paper = paper;
        display();
    }
    public void display(){
        System.out.println("paper :"+paper);
    }

}
class Subscriber{//订阅者刘能
    private String paper;
    private Newspapers newspapers;
    public Subscriber(Newspapers newspapers) {
        this.newspapers = newspapers;
        newspapers.registerObserver(this);
    }
    public void update(String paper){
        this.paper = paper;
        display();
    }
    public void display(){
        System.out.println("paper :"+paper);
    }

}

接着我们写一个测试类

接着我们写一个测试类

public class Test {
    public static void main(String[] args) {
        Newspapers newspapers = new Newspapers();
        Subscriber subscriber = new Subscriber(newspapers);
        newspapers.setPaper("今日说法");
    }
}
public class Test {
    public static void main(String[] args) {
        Newspapers newspapers = new Newspapers();
        Subscriber subscriber = new Subscriber(newspapers);
        newspapers.setPaper("今日说法");
    }
}

测试结果:报刊出现新的报纸,然后提醒它的所有订阅者

测试结果:报刊出现新的报纸,然后提醒它的所有订阅者

图片 1

图片 2

 

 

这个功能到此就算是实现完了,但是,这时候我们接到了报社的电话:报社告诉我们谢大脚和王小蒙也订阅了报纸,当报社有新的报纸时我们不仅要给刘能发,还要给谢大脚和王小蒙也发一份=。=

这个功能到此就算是实现完了,但是,这时候我们接到了报社的电话:报社告诉我们谢大脚和王小蒙也订阅了报纸,当报社有新的报纸时我们不仅要给刘能发,还要给谢大脚和王小蒙也发一份=。=

我们发现,这时我们需要再分别写两个类来代表谢大脚和王小蒙,但是Newspapers类中我们怎么来写?我们的订阅和注册已经写死了只支持刘能!其实订阅报纸本就是一个一对多的关系,而我们经过了上一章的学习,发现这种实现方式有很多地方是不对的,针对具体实现编程,会导致我们以后在订阅或退订时必须修改程序,所以我们应该想到使用接口。在这里,我们把报刊称为“主题”(Subject),而订阅者称为

我们发现,这时我们需要再分别写两个类来代表谢大脚和王小蒙,但是Newspapers类中我们怎么来写?我们的订阅和注册已经写死了只支持刘能!其实订阅报纸本就是一个一对多的关系,而我们经过了上一章的学习,发现这种实现方式有很多地方是不对的,针对具体实现编程,会导致我们以后在订阅或退订时必须修改程序,所以我们应该想到使用接口。在这里,我们把报刊称为“主题”(Subject),而订阅者称为

“观察者(Observer)”,让我们来看的更仔细点:

“观察者(Observer)”,让我们来看的更仔细点:

图片 3

图片 4

主题和观察者定义了一对多的关系,观察者依赖于此主题,只要主题状态一有改变,观察者就会被通知。根据通知的风格,观察者可能因此而更新。

主题和观察者定义了一对多的关系,观察者依赖于此主题,只要主题状态一有改变,观察者就会被通知。根据通知的风格,观察者可能因此而更新。

① 我们定义一个主题接口Subject,它除了注册和撤销方法之外,还拥有notifyObservers()方法,此方法用于在状态改变时更新所有当前观察者。对象只有使用此接口注册为观察者,或者把自己从观察者中删除。

① 我们定义一个主题接口Subject,它除了注册和撤销方法之外,还拥有notifyObservers()方法,此方法用于在状态改变时更新所有当前观察者。对象只有使用此接口注册为观察者,或者把自己从观察者中删除。

② 接下来我们定义一个观察者接口Observer,所有潜在的观察者必须实现此接口,它只拥有一个公共方法update,当主题状态改变时,它被调用。具体的观察者可以是实现此接口的任意类,观察者必须注册具体主题,以便接受更新。

② 接下来我们定义一个观察者接口Observer,所有潜在的观察者必须实现此接口,它只拥有一个公共方法update,当主题状态改变时,它被调用。具体的观察者可以是实现此接口的任意类,观察者必须注册具体主题,以便接受更新。

③此外,我们还需要一个接口DisplayElement用来显示

③此外,我们还需要一个接口DisplayElement用来显示

下面我们来实现一下:

下面我们来实现一下:

public interface Subject{
    public void registerObserver(Observer observer);//注册观察者
    public void removeObserver(Observer observer);//移除观察者
    public void notifyObservers();//当主题状态改变,调用这个方法通知观察者
}

public interface Observer {
    public void update(String paper);//此方法当产生改变的时候由主题调用,
}

public interface DisplayElement{
     public void display();//显示
}
public interface Subject{
    public void registerObserver(Observer observer);//注册观察者
    public void removeObserver(Observer observer);//移除观察者
    public void notifyObservers();//当主题状态改变,调用这个方法通知观察者
}

public interface Observer {
    public void update(String paper);//此方法当产生改变的时候由主题调用,
}

public interface DisplayElement{
     public void display();//显示
}

下面是主题实现类:

下面是主题实现类:

//主题(报社)
public class Newspapers implements Subject{
    private ArrayList<Observer> observers ;
    private String paper;

    public Newspapers() {
        observers = new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);

    }

    @Override
    public void removeObserver(Observer observer) {
        int index = observers.indexOf(observer);
        if(index >= 0){
            observers.remove(index);
        }

    }

    public void setMeasurements(String paper){
        this.paper = paper;
        measurementsChanged();//当有新报纸时调用此方法
    }

    public void measurementsChanged(){
        notifyObservers();
    }

    @Override
    public void notifyObservers() {//调用此方法通知所有观察者
        for(int i=0;i<observers.size();i++){
            Observer observer = observers.get(i);
            observer.update(paper);//更新报纸
        }

    }

}
//主题(报社)
public class Newspapers implements Subject{
    private ArrayList<Observer> observers ;
    private String paper;

    public Newspapers() {
        observers = new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);

    }

    @Override
    public void removeObserver(Observer observer) {
        int index = observers.indexOf(observer);
        if(index >= 0){
            observers.remove(index);
        }

    }

    public void setMeasurements(String paper){
        this.paper = paper;
        measurementsChanged();//当有新报纸时调用此方法
    }

    public void measurementsChanged(){
        notifyObservers();
    }

    @Override
    public void notifyObservers() {//调用此方法通知所有观察者
        for(int i=0;i<observers.size();i++){
            Observer observer = observers.get(i);
            observer.update(paper);//更新报纸
        }

    }

}

本文由美高梅网址注册发布于澳门mgm4858集团登录网址,转载请注明出处:当一个对象改变状态时,就可以使用观察者模式

关键词: