首页 > 代码库 > 观察者模式

观察者模式

概述:

观察者模式主要用于1N的通知,当一个对象(目标对象)的状态改变时,他需要及时告知其他一系列对象(观察者),令他们做出相应的响应。

观察者模式有两种形式,推和拉。这里用电台广播做例子。

使用场景:

1、关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系

2、事件多级触发场景

观察者的角色:

1、抽象被观察者:提供一个接口,可以新增、删除、通知观察者

2、具体被观察者:具体主题改变时,将对于信息发送给观察者

3、抽象观察者:定义一个更新的接口,以便接受被观察者的信息

4、具体观察者:实现抽象观察者,获取被观察者的信息。

 

一、推模式:每次都会把通知以广播方式发生给所有观察者,所有观察者只能被动接受。

1定义听众抽象类(抽象观察者):

public interface Audience {
    //接收信息
    public void receiveInfo(String message);
}

2、义具体听众(具体观察者):这里分别定义一个喜欢旅游者和程序猿

public class Tourist implements Audience{  //旅游者
    private String name;
    
    public Tourist(String name){
        this.name = name;
    }

    @Override
    public void receiveInfo(String message) {
        System.out.println(name+":"+message);
    }
}

public class Programmer implements Audience {   //程序猿

    private String name;
    
    public Programmer(String name){
        this.name = name;
    }

    @Override
    public void receiveInfo(String message) {
        System.out.println(name+":"+message);
    }
}

3、定义一个抽象被观察者

public interface Subject {
    //添加观察者
    public void addAudience(Audience audience);
    //删除观察者
    public void delAudience(Audience audience);
    //通知观察者
    public void notifyAudience(String message);
}

4、定义一个被观察者(电台):

public class RadioSation implements Subject {
    List<Audience> audienceList = new ArrayList<Audience>();

    //通知观察者
    @Override
    public void addAudience(Audience audience) {
        audienceList.add(audience);
    }

    //删除观察者
    @Override
    public void delAudience(Audience audience) {
        audienceList.remove(audience);
    }

    @Override
    public void notifyAudience(String message) {
        for(Audience audience:audienceList){
            audience.receiveInfo(message);
        }
    }
}

这样观察者模式已经实现,我们模拟电台发送信息

public class ObservationClient {
    public static void main(String[] args) {
        //定义观察者
        Audience programmer = new Programmer("程序员");
        Audience  tourist   = new Tourist("游者");
        
        //定义被观察者(电台)
        Subject radioSation = new RadioSation();
        radioSation.addAudience(programmer);
        radioSation.addAudience(tourist);
        radioSation.notifyAudience("华山免费两日游");
    }
}

执行结果:

技术分享

   从上面的例子可以看出,电台听众可以接受到电台的信息,当只能被动的接收,这些信息可能是听众不需要的(程序员不想知道旅游信息)。如果我们要实现听众可以自主的选择要接受的内容,就需要使用拉模式。

 

二、拉模式:观察者只要知道情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定(把这个被观察者的信息扔个观察者)

1、定义一个抽象被观察者(修改notifyAudience方法,添加发布信息)

public interface Subject {
    //添加观察者
    public void addAudience(Audience audience);
    //删除观察者
    public void delAudience(Audience audience);
    //发布信息(分别是旅游信息、it信息)
    public void releaseInfo(String touristInformation,String itInformation);
    //通知观察者
    public void notifyAudience();
}

2、定义被观察者(电台),分别定义获取it信息和旅游信息,是为了让观察者选择自己喜欢信息

public class RadioSation implements Subject {
    List<Audience> audienceList = new ArrayList<Audience>();
    private String touristInformation;     //旅游信息
    private String itInformation;          //it信息

    //通知观察者
    @Override
    public void addAudience(Audience audience) {
        audienceList.add(audience);
    }

    //删除观察者
    @Override
    public void delAudience(Audience audience) {
        audienceList.remove(audience);
    }
    
    //发布信息
    @Override
    public void releaseInfo(String touristInformation, String itInformation) {
        this.setTouristInformation(touristInformation);
        this.setItInformation(itInformation);    
    }

    @Override
    public void notifyAudience() {
        for(Audience audience:audienceList){
            audience.receiveInfo(this);
        }
    }

    public String getTouristInformation() {
        return touristInformation;
    }

    public void setTouristInformation(String touristInformation) {
        this.touristInformation = touristInformation;
    }

    public String getItInformation() {
        return itInformation;
    }

    public void setItInformation(String itInformation) {
        this.itInformation = itInformation;
    }
}

3、定义听众抽象类(抽象观察者):

public interface Audience {
    //接收信息(接受整个电台)
    public void receiveInfo(Subject subject);
}

4、定义具体听众(具体观察者):这里分别定义一个喜欢旅游者和程序猿

public class Tourist implements Audience{  //旅游者
    private String name;
    
    public Tourist(String name){
        this.name = name;
    }

    @Override
    public void receiveInfo(Subject subject) {
        //获取旅游方面的信息
        System.out.println(name+":"+((RadioSation)subject).getTouristInformation());
    }
}

public class Programmer implements Audience {   //程序猿

    private String name;
    
    public Programmer(String name){
        this.name = name;
    }

    @Override
    public void receiveInfo(Subject subject) {
        //获取it方面的信息
        System.out.println(name+":"+((RadioSation)subject).getItInformation());
    }
}

模拟电台发送信息:

public class ObservationClient {
    public static void main(String[] args) {
        //定义观察者
        Audience programmer = new Programmer("程序员");
        Audience  tourist   = new Tourist("游者");
        
        //定义被观察者(电台)
        Subject radioSation = new RadioSation();
        radioSation.addAudience(programmer);
        radioSation.addAudience(tourist);
        //发布信息
        radioSation.releaseInfo("华山两天免费游","jdk已经出8了");
        radioSation.notifyAudience();
    }
}

输出结果:

技术分享

这样就实现了,具体观众获取自己想要的电台信息。

 

O(∩_∩)O  Done!  

 

观察者模式