observer

来源:互联网 发布:成都家政公司办公软件 编辑:程序博客网 时间:2024/06/05 14:20

这是我从《Head First 设计模式》这本书中学习到的第二个模式  观察者模式,其主要讲解了对象之间的一对多依赖,当一个对象的状态改变时,这个对象的观察者都会接收到通知并获取更新的数据。原书中用一个气象监测应用讲解了这个模式。我根据理解创建了一个关于 NBA球迷订阅各个球队战况的应用。具体实现看代码

1:首先新建三个接口 这三个接口分别是 Subject.java\Observer.java\DisplayElement.java。所有被观察者必须实现Subject.java这个接口用于管理观察者。所有观察者必须实现Observer.java\DisplayElement.java这两个接口,第一个接口定义个当被观察者数据更新时通知观察者的方法即update方法,第二个接口定义了一个所有观察者处理被观察者传递过来的数据的方法。


public interface Subject {/** * 新增粉丝(观察者) * @param o (观察者) */void registerObserver(Observer o);/** * 删除新增粉丝(观察者) * @param o (观察者) */void removeObserver(Observer o);/** * 发送消息给粉丝(观察者) */void notifyObservers();}public interface Observer {/** * 当被观察者数据更新时通过这个方法告知观察者 * @param data 被观察者传递给观察者的数据 */void update(Data data);}public interface DisplayElement {/** * 处理被观察者传递过来的数据 */void display();}

2 定义一个数据类来体现数据 (各个属性的getter、setter就没有拷贝le)

public class Data {private String teamName;private LocalDate date;private double score;private boolean win;public Data(String teamName,LocalDate date,double score,boolean win){this.teamName = teamName;this.date = date;this.score = score;this.win = win;}@Overridepublic String toString(){return this.teamName+"在"+this.date+"的比赛中,全队得分:"+this.score+","+(this.win ? "赢得" : "输掉") +"了比赛";}}

3 定义两个被观察者类(骑士队和火箭队)

public class Cavaliers implements Subject{/** * 骑士队的数据 */private Data data;/** * 骑士队的粉丝 */private static List<Observer> observers;private static Cavaliers cavaliers;private Cavaliers() {observers = Collections.synchronizedList(new ArrayList<>(8));}/** * 获取骑士队的实例 */public static Cavaliers getInstance(){if(null == cavaliers){return new Cavaliers();}return cavaliers;}/** * 新增骑士队的粉丝 */@Overridepublic void registerObserver(Observer o) {if(Objects.isNull(o)){return ;}observers.add(o);}/** * 删除骑士队的粉丝 */@Overridepublic void removeObserver(Observer o) {if(Objects.isNull(o)){return ;}int i = observers.indexOf(o);if(i > -1){observers.remove(i);}}/** * 当有骑士队的数据传来时,通知骑士队的粉丝 */@Overridepublic void notifyObservers() {for(Observer observer : observers){observer.update(data);}}/** * 当骑士队的数据改变时,将数据传给骑士队的观察者 * @param data */public void changed(Data data){this.data = data;notifyObservers();}}public class Rocket implements Subject{private Data data;/** * 火箭队的粉丝 */private List<Observer> observers;private static Rocket rocket;private Rocket(){observers = Collections.synchronizedList(new ArrayList<>(1024));}public static Rocket getInstance(){if(null == rocket){return new Rocket();}return rocket;}/** * 新增火箭队的粉丝 */@Overridepublic void registerObserver(Observer o) {if(null == o){return;}observers.add(o);}/** * 删除火箭队的粉丝 */@Overridepublic void removeObserver(Observer o) {if(null == o){return;}int i = observers.indexOf(o);if(i > -1){observers.remove(i);}}/** * 当有火箭队的数据传来时,通知火箭队的粉丝 */@Overridepublic void notifyObservers() {for(Observer observer : observers){observer.update(data);}}/** * 当火箭队的数据改变时,将数据传给火箭队的观察者 * @param data */public void changed(Data data){this.data = data;notifyObservers();}}

4 新建一个测试类,测试订阅和解除订阅功能

public class Test {public static void main(String[] args) throws InterruptedException{Cavaliers cavaliers = Cavaliers.getInstance();Rocket rocket = Rocket.getInstance();Person person1 = new Person();//person1 订阅骑士队cavaliers.registerObserver(person1);//person1 订阅火箭队rocket.registerObserver(person1);Data data = new Data("克利夫兰骑士队", LocalDate.now(), 98, true);cavaliers.changed(data);Person person2 = new Person();//person2 订阅骑士队cavaliers.registerObserver(person1);//person2 订阅火箭队rocket.registerObserver(person2);Thread.sleep(2000);Data data2 = new Data("克利夫兰骑士队", LocalDate.now().plusDays(2), 100, false);cavaliers.changed(data2);Thread.sleep(2000);//person1 解除订阅骑士队cavaliers.removeObserver(person1);cavaliers.changed(data2);Data data3 = new Data("休斯顿火箭队", LocalDate.now().plusDays(5), 120, true);rocket.changed(data3);}}

输出结果:

克利夫兰骑士队在2017-07-16的比赛中,全队得分:98.0,赢得了比赛
克利夫兰骑士队在2017-07-18的比赛中,全队得分:100.0,输掉了比赛
克利夫兰骑士队在2017-07-18的比赛中,全队得分:100.0,输掉了比赛
克利夫兰骑士队在2017-07-18的比赛中,全队得分:100.0,输掉了比赛
休斯顿火箭队在2017-07-21的比赛中,全队得分:120.0,赢得了比赛
休斯顿火箭队在2017-07-21的比赛中,全队得分:120.0,赢得了比赛








原创粉丝点击