观察者模式

观察者模式又叫(发布-订阅)模式,观察者通过监听某个主题,一旦主题的状态发生改变,则自动通知观察者。

类型:

行为型模式(类与类之间的行为型模式)

观察者模式中设计的角色:

  • 抽象主题(Subject):定义具体主题所需的注册,删除和通知观察者的方法接口。
  • 具体主题(具体被观察者):具体主题的状态发生改变时,则通知这个主题的观察者。
  • 抽象观察者(Observer):得知具体主题发生改变时更新自己,通过抽象的形式,可以使得观察者和主题之间实现松耦合。
  • 具体观察者:可以自主的选择与主题之间的状态,订阅主题,或者取消订阅主题。

观察者模式关系图:

java观察者uml图 java 观察者模式例子_观察者模式

观察者模式示例:

本例子是以关注博客为例,关注了博客即成为博主的粉丝,在博主更新了博客之后,会通知所有的粉丝。同时每一个具体的观察者都可以选择是否成为博主的粉丝。

抽象主题接口:

/**
 * Create by zhaihongwei on 2018/3/26
 * 抽象的主题对象
 */
public interface Subject {

    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObserver();
}

具体的主题类

/**
 * Create by zhaihongwei on 2018/3/26
 * 具体的主题对象
 * 我的博客类
 */
public class MyBlog implements Subject {

    // 用来保存所有粉丝的容器
    private ArrayList<Observer> observers = new ArrayList();

    /**
     * 哎呀,又有一个新的粉丝了开心。我记住你了哟!!!
     * @param observer
     */
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    /**
     * 555...,失去了一个粉丝,你怎么可以取消关注呢!期待与你再次相遇!
     * @param observer
     */
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 我写了一篇新的Blog,我要通知我所有的粉丝过来看。
     */
    @Override
    public void notifyObserver() {
        // 遍历所有的粉丝,并通知他们,我更新blog了
        for (Observer observer : observers) {
            observer.update("亲爱的"+ observer.getClass() +",我新写了一篇blog,记得来看哦!");
        }
    }
}

抽象观察者接口:

/**
 * Create by zhaihongwei on 2018/3/26
 * 抽象观察者对象
 * 通过抽象的观察对象,将主题对象和观察者对象之间实现松耦合。
 */
public interface Observer {
    /**
     * 更新状态
     * @param newBlog
     */
    void update(String newBlog);
}

具体的观察者对象:

/**
 * Create by zhaihongwei on 2018/3/26
* 粉丝A
 */
public class FansA implements Observer {

    @Override
    public void update(String newBlog) {
        System.out.println(newBlog);
    }
}
/**
 * Create by zhaihongwei on 2018/3/26
* 粉丝B
 */
public class FansB implements Observer {

    @Override
    public void update(String newBlog) {
        System.out.println(newBlog);
    }
}

测试类:

/**
 * Create by zhaihongwei on 2018/3/26
 * 测试类
 */
public class ObserverTest {

    public static void main(String[] args) {
        // 创建我的blog对象
        Subject myBlog = new MyBlog();

        // 创建粉丝对象
        FansA fansA = new FansA();
        FansB fansB = new FansB();

        // A,B关注了我(点击了关注按钮),成为了我的粉丝
        myBlog.registerObserver(fansA);
        myBlog.registerObserver(fansB);

        // 我写了一篇新的Blog,通知我的粉丝
        myBlog.notifyObserver();

        System.out.println("----------------------------------------");

        // 555... FanB不再关注我了,以后我写的blog不能通知他了
        myBlog.removeObserver(fansB);
        // 我又写了一篇新的Blog,通知我的粉丝
        myBlog.notifyObserver();
    }
}

测试结果:

亲爱的class observer.FansA,我新写了一篇blog,记得来看哦!
亲爱的class observer.FansB,我新写了一篇blog,记得来看哦!
----------------------------------------
亲爱的class observer.FansA,我新写了一篇blog,记得来看哦!

总结:

通过以上示例,相信大家已经对观察者模式有所了解了,粉丝通过点击关注按钮,成为博主粉丝,博主在更新了博客之后会自动通知所有的粉丝。

问题:

我发布了博客,已经通知了粉丝,但是我突然发现写的有点小问题,我修改了一下博客,又会再通知一次我的粉丝,这样就不太友好了。可以做如下改变:

修改MyBlog类:

/**
 * Create by zhaihongwei on 2018/3/26
 * 具体的主题对象
 * 我的博客类
 */
public class MyBlog implements Subject {

    // 确认博客是否能发布,默认为false
    private boolean isPublication;

    // 用来保存所有粉丝的容器
    private ArrayList<Observer> observers = new ArrayList();

    /**
     * 哎呀,又有一个新的粉丝了开心。我记住你了哟!!!
     * @param observer
     */
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    /**
     * 555...,失去了一个粉丝,你怎么可以取消关注呢!期待与你再次相遇!
     * @param observer
     */
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 我写了一篇新的Blog,我要通知我所有的粉丝过来看。
     */
    @Override
    public void notifyObserver() {
        if (isPublication) {
            // 遍历所有的粉丝,并通知他们,我更新blog了
            for (Observer observer : observers) {
                observer.update("亲爱的"+ observer.getClass() +",我新写了一篇blog,记得来看哦!");
            }
        }
    }

    public boolean setIsPublication() {
        System.out.println("我已经确认博客可以发布了,快来看吧!");
        isPublication=true;
        return isPublication;
    }
}

修改测试类:

/**
 * Create by zhaihongwei on 2018/3/26
 * 测试类
 */
public class ObserverTest {

    public static void main(String[] args) {
        // 创建我的blog对象
        MyBlog myBlog = new MyBlog();

        // 创建粉丝对象
        FansA fansA = new FansA();
        FansB fansB = new FansB();

        // A,B关注了我(点击了关注按钮),成为了我的粉丝
        myBlog.registerObserver(fansA);
        myBlog.registerObserver(fansB);

        // 我写了一篇新的Blog,并且确认博客可以发布了
        myBlog.setIsPublication();
        // 通知我的粉丝
        myBlog.notifyObserver();

        System.out.println("----------------------------------------");

        // 555... FanB不再关注我了,以后我写的blog不能通知他了
        myBlog.removeObserver(fansB);
        // 我又写了一篇新的Blog,通知我的粉丝
        myBlog.notifyObserver();
    }
}

总结:

这样做之后,是否通知粉丝就变成可控的了,在我写好博客,并且确认无误后,我再去通知粉丝博客更新了,测试结果是一样的,这里没有再贴出来了。