我的武林秘籍设计模式之观察者模式

自从jack的鸭子游戏得到成功之后,jack的好朋友夏流就觉得心里痒痒的,也想做出一番作为来。

所以,今天的主人公就是这位夏流童鞋。夏流是钱塘江观测站的一名观测员,需要向人民群众反馈钱塘江的水位,水温,风力,及水里的鱼量等信息。在这里经常会有许多市民从他这里打听当日的钱塘江的这些信息,以便于他们了解,好决定是不是要去江边做点什么。

于是夏流决定做一个系统,能够自动反馈钱塘江的信息给热心市民。每当钱塘江的相关信息有变化时,会自动发送到热心市民手机上,通知他们。

在观察者模式中,夏流做的这个钱塘江观测系统便是一个主题(Subject),热心市民便是一个观察者(Observer)

我们定义两个接口Subject和Observer ,因为我们是有格局,有情怀的程序猿,所以一般我们都是要面向接口编程。

在Subject中,我们定义三个方法,添加观察者,删除观察者,通知观察者。

在Observer中,只要更新主题发过来的消息就好,所以只有一个更新方法。

然后我们实现具体主题,也就是钱塘江观测站,在钱塘江观测站中,水位,水温,风力,鱼的条数都是它的属性,还有一个是观察者列表,所有的观察者都存在这个ObserverList里。当有新的信息更新时,他就调用notifyObserver方法通知他们的观察者去更新信息。

接着呢是实现观察者了,这个市民就是具体的观察者了。观察者中维护了一个主题,这个主题就是他关注的那个主题,也就是钱塘江观测站了,它有了这个主题就能够把自己给添加到这个主题的观察者列表中了。

夏流按照这个思路设计完了该系统,却遭到了一些热心市民的抱怨。一位爱钓鱼的王大伯说,我只要当天的水位和鱼的数量信息,其他信息这么多给我并没有软用。

另一位爱游泳的刘叔叔说,我只要水温很风力信息就够了,这样我才能知道我该不该下水游泳(当然在钱塘江游泳钓鱼啥的都是非常危险的,这里只是举个例子)

另一位爱拍照的王阿姨说,我只要风力信息,希望我能借助风力吹起我美丽的秀发,用我的美颜相机定格住那美丽的瞬间

夏流听到了各位热心市民的意见,决定改善一下系统。

他想这样的话,就在通知观察者的时候,让update方法不带参数。反正他们内部已经维护了一个主题,让他们自己根据自己所需去从这个主题中拿数据就好了。

以下是修改后的类图

主要还是修改观察者中的update方法,一个是直接通过update方法一股脑把所有信息传过来,另一个是通过观察者自身所维护的主题中去取。

接着有了这个设计,我们好实现代码了

package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public interface Observer {
    void update();

    void display();
}
package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public interface Subject {
     void addObserver(Observer observer);
     void deleteObserver(Observer observer);
     void notifyObserver();
}
package qiantang;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by huangx on 2018/11/14.
 */
public class QiangtangRiverStation implements Subject {

    private int height;
    private int tempature;
    private int wind;
    private int fish;
    private List<Observer> observerList = new ArrayList<Observer>();

    public void addObserver(Observer observer) {
        observerList.add(observer);
    }

    public void deleteObserver(Observer observer) {
        observerList.remove(observer);
    }

    public void notifyObserver() {
        for (Observer observer : observerList) {
            observer.update();
        }
    }

    public void setNewInfo(int height, int tempature, int wind, int fish) {
        this.height = height;
        this.tempature = tempature;
        this.wind = wind;
        this.fish = fish;
        notifyObserver();
    }

    public int getHeight() {
        return height;
    }

    public int getTempature() {
        return tempature;
    }

    public int getWind() {
        return wind;
    }

    public int getFish() {
        return fish;
    }

}
package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public class FishCitizen implements Observer {
    private String name;
    private int fish;
    private int height;
    private Subject subject;

    public FishCitizen(String name, Subject subject) {
        this.name = name;
        this.subject = subject;
        subject.addObserver(this);//关键一步把自己扔到主题中去
    }

    public void update() {
        if (subject instanceof QiangtangRiverStation) {
            this.fish = ((QiangtangRiverStation) subject).getFish();
            this.height = ((QiangtangRiverStation) subject).getHeight();
        }
        display();
    }

    public void display() {
        System.out.println("我是" + name + ",今天的鱼量是" + fish + ",今天 的水位是" + height);
    }
}
package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public class PhotoCitizen implements Observer {
    private String name;
    private int wind;
    private Subject subject;

    public PhotoCitizen(String name, Subject subject) {
        this.name = name;
        this.subject = subject;
        subject.addObserver(this);
    }

    public void update() {
        if (subject instanceof QiangtangRiverStation) {
            this.wind = ((QiangtangRiverStation) subject).getWind();
        }
        display();
    }

    public void display() {
        System.out.println("我是" + name + ",今天的风力是" + wind + "今天的我一定是个小公举");
    }
}
package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public class SwimCitizen implements Observer {
    private String name;
    private int tempature;
    private int wind;
    private Subject subject;

    public SwimCitizen(String name, Subject subject) {
        this.name = name;
        this.subject = subject;
        subject.addObserver(this);
    }

    public void update() {
        if (subject instanceof QiangtangRiverStation) {
            this.tempature = ((QiangtangRiverStation) subject).getTempature();
            this.wind = ((QiangtangRiverStation) subject).getWind();
        }
        display();
    }

    public void display() {
        System.out.println("我是" + name + ",今天的水温是" + tempature + ",今天 的风力是" + wind);
    }
}
package qiantang;

/**
 * Created by huangx on 2018/11/14.
 */
public class TestApplication {
    public static void main(String[] args) {
        QiangtangRiverStation qiangtangRiverStation=new QiangtangRiverStation();
        SwimCitizen swimCitizen=new SwimCitizen("刘叔叔",qiangtangRiverStation);
        FishCitizen fishCitizen=new FishCitizen("王大伯",qiangtangRiverStation);
        PhotoCitizen photoCitizen=new PhotoCitizen("王阿姨",qiangtangRiverStation);
        qiangtangRiverStation.setNewInfo(11,22,33,44);
        qiangtangRiverStation.setNewInfo(55,66,77,88);
    }
}

运行结果:

有了这个设计,夏流童鞋不仅受到了大伯大妈的好评,也帮助他成为杭州杰出青年的好榜样。

观察者模式的官方定义是:定义对象见的一种一对多的依赖关系,当一个对象的状态发送变化时,所有依赖它的对象都得到通知并被自动更新。

猜你喜欢

转载自blog.csdn.net/huang_happy/article/details/84075228