初探观察者模式

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

场景:有这样一个需求,风险监控的时候,某个用户关注了某个信息,并且希望这个信息有重大变动的时候能够往邮箱、手机、当前用户登录的网页发送这个信息。

让我们来看看根据需求马上动手的代码:

1、定义发送信息的类

package pattern.observer;

public class SendEmail {
    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
    }
}

public class SendPhone {
    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:"+message + "。该信息来自XXXX");
    }
}

public class SendWeb {
    public void show(String message){
        System.out.println("您订阅的信息有更新,更新内容:"+message);
    }
}

2、获取改变的信息并发送

public void messageChange(String message){
        SendEmail sendEmail = new SendEmail();
        SendPhone sendPhone = new SendPhone();
        SendWeb sendWeb = new SendWeb();

        sendEmail.show(message);
        sendPhone.show(message);
        sendWeb.show(message);
    }

我们来分析一下这样写代码的不足:首先,发送信息类里面的show()方法看起来像一个统一的接口,我们可以封装起来;其次,针对具体实现变成,这样会导致我们增加或删除一个发送通知的类时,我们必须要修改实现类。

 

接下来,我们分析一下观察者模式是怎么实现对象一对多的情况的。

首先实现主题接口和观察者接口

package pattern.observer;

public interface Subject {
    //注册观察者(就是发送信息的类)
    public void registerObserver(Observer observer);
    //删除观察者
    public void removeObserver(Observer observer);
    //通知观察者信息已经改变
    public void notifyObservers();
}

public interface Observer {
    //观察者接口,一旦信息有改变,执行更新操作
    public void update(String message);
}

然后信息实现主题(Object)接口

package pattern.observer;

import java.util.ArrayList;

public class Message implements Subject{
    private String message;
    private ArrayList observers;

    public Message(){
        observers = new ArrayList();
    }

    //一旦信息符合要求,通知观察者更新信息
    public void messageChange(){
        if(message.equals("重大变化")){
            notifyObservers();
        }
    }

    //有信息进来就调用信息改变的方法
    public void setMessage(String message){
        this.message = message;
        messageChange();
    }

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

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

    @Override
    public void notifyObservers() {
        for(Object observer:observers){
            Observer o = (Observer)observer;
            o.update(message);
        }
    }
}

发送信息的类实现观察者(Observer)接口

package pattern.observer;

public class SendEmail implements Observer{
    private Subject subject;

    public SendEmail(Subject subject){
        this.subject = subject;
        subject.registerObserver(this);
    }

    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
    }

    @Override
    public void update(String message) {
        show(message);
    }
}

public class SendPhone implements Observer{
    private Subject subject;

    public SendPhone(Subject subject){
        this.subject = subject;
        subject.registerObserver(this);
    }

    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:"+message + "。该信息来自XXXX");
    }

    @Override
    public void update(String message) {
        show(message);
    }
}

public class SendWeb implements Observer{
    private Subject subject;

    public SendWeb(Subject subject){
        this.subject = subject;
        subject.registerObserver(this);
    }

    public void show(String message){
        System.out.println("您订阅的信息有更新,更新内容:"+message);
    }

    @Override
    public void update(String message) {
        show(message);
    }
}

最后实现控制器进行测试

package pattern.observer;

public class MessageController {

    public static void main(String[] args) {
        String messageStr = "重大变化";
        Message message = new Message();
        SendPhone sendPhone = new SendPhone(message);
        SendWeb sendWeb = new SendWeb(message);
        SendEmail sendEmail = new SendEmail(message);

        message.setMessage(messageStr);
    }

}

至此观察者模式完毕。


其实还有个疑问,为什么要在观察者本身里面注册呢?

public class SendEmail implements Observer{
    private Subject subject;

    public SendEmail(Subject subject){
        this.subject = subject;
        //为什么要在观察者保存Subject并且在初始化的时候用来注册
        subject.registerObserver(this);
    }

    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
    }

    @Override
    public void update(String message) {
        show(message);
    }
}

是不是希望可以在观察者本身取消对消息的订阅?

public class SendEmail implements Observer{
    private Subject subject;

    public SendEmail(Subject subject){
        this.subject = subject;
        this.subject.registerObserver(this);
    }

    public void show(String message){
        System.out.println("您在XXX订阅的信息有更新,更新内容:" + message + "。该信息来自XXX邮箱");
    }

    @Override
    public void update(String message) {
        show(message);
    }

    //取消订阅
    public void unsubscribe(){
        subject.removeObserver(this);
    }
}

 

posted @ 2018-08-07 15:54  YzdFly  阅读(101)  评论(0编辑  收藏  举报