观察者模式

观察者模式又称为发布订阅模式:多个对象同时观察一个对象,一个对象的改变引起多个对象的改变

定义被观察者:

package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 * 定义被观察者接口
 */
public interface Observable {
    /**
     * 添加观察者
     * @param observer
     */
    void addObserver(Observer observer);

    /**
     * 移除观察者
     * @param observer
     */
    void removeObserver(Observer observer);

    /**
     * 通知所有观察者内容
     * @param content 通知内容
     */
    void notifyObservers(String content);
}

定义被观察者统一实现父类:

package com.whereta.observer;

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

/**
 * Vincent 创建于 2016/5/3.
 * 被观察者统一的父类对象
 */
public class Subject implements Observable {

    private final List<Observer> observerList=new ArrayList<Observer>();

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

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

    public void notifyObservers(String content) {
        for(Observer observer:observerList){
            observer.update(content);
        }
    }
}

定义具体实现类:

package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 * 被观察者具体实现对象:小明
 */
public class XiaoMing extends Subject {

    public void eat() {
        System.out.println("小明吃饭了。。。开始通知观察者");
        super.notifyObservers("小明吃饭了");
    }


    public void run() {
        System.out.println("小明跑步了。。。开始通知观察者");
        super.notifyObservers("小明跑步了");
    }

}

定义观察者接口:

package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 * 观察者接口
 */
public interface Observer {
    /**
     * 被观察者如果有变化 ,调用该接口通知观察者
     * @param content
     */
    void update(String content);

}

定义具体实现类:父亲和母亲

package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 * 父亲:观察者
 */
public class Father implements Observer {
    public void update(String content) {
        System.out.println("父亲观察到小明有变化:"+content);
    }
}
package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 */
public class Mother implements Observer {
    public void update(String content) {
        System.out.println("母亲观察到小明有变化:"+content);
    }
}

测试:

package com.whereta.observer;

/**
 * Vincent 创建于 2016/5/3.
 * 母亲:观察者
 */
public class Main {
    public static void main(String[] args) {

        Observer father=new Father();
        Observer mother=new Mother();

        XiaoMing xiaoMing=new XiaoMing();
        xiaoMing.addObserver(father);
        xiaoMing.addObserver(mother);

        xiaoMing.eat();
        xiaoMing.run();

    }
}

输出:

小明吃饭了。。。开始通知观察者
父亲观察到小明有变化:小明吃饭了
母亲观察到小明有变化:小明吃饭了
小明跑步了。。。开始通知观察者
父亲观察到小明有变化:小明跑步了
母亲观察到小明有变化:小明跑步了

现在看Subject类,有两点可以优化下:

  1. 观察者集合并不是线程安全的

  2. 如果在通知一个观察者时耗时很长会卡主整个线程

现在我们来改造下:

package com.whereta.observer;

import java.util.List;
import java.util.Vector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Vincent 创建于 2016/5/3.
 * 被观察者统一的父类对象
 */
public class Subject implements Observable {

    private final List<Observer> observerList = new Vector<Observer>();

    private final Executor executor = Executors.newFixedThreadPool(10);

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

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

    public void notifyObservers(String content) {

        final String temp = content;

        for (Observer observer : observerList) {
            final Observer o = observer;
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        o.update(temp);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}


  1. Vector是线程安全的集合

  2. 添加线程池,通过多线程通知每个观察者

以上是我们自定义的观察者和被观察者接口,其实在jdk中已经定义了相关接口,现在我们来通过实现jdk中的观察者和被观察者接口完成以上功能

package com.whereta.observer.jdk;

import java.util.Observable;

/**
 * Vincent 创建于 2016/5/3.
 */
public class XiaoMing extends Observable {
    public void eat() {
        System.out.println("小明吃饭了。。。开始通知观察者");
        super.setChanged();
        super.notifyObservers("小明吃饭了");
    }


    public void run() {
        System.out.println("小明跑步了。。。开始通知观察者");
        super.setChanged();

        super.notifyObservers("小明跑步了");
    }
}
package com.whereta.observer.jdk;


import java.util.Observable;
import java.util.Observer;

/**
 * Vincent 创建于 2016/5/3.
 * 父亲:观察者
 */
public class Father implements Observer {

    public void update(Observable o, Object arg) {
        System.out.println("父亲观察到小明有变化:" + arg.toString());

    }
}
package com.whereta.observer.jdk;


import java.util.Observable;
import java.util.Observer;

/**
 * Vincent 创建于 2016/5/3.
 */
public class Mother implements Observer {

    public void update(Observable o, Object arg) {
        System.out.println("母亲观察到小明有变化:" + arg.toString());

    }
}
package com.whereta.observer.jdk;

import java.util.Observer;

/**
 * Vincent 创建于 2016/5/3.
 */
public class Main {
    public static void main(String[] args) {
        Observer father=new Father();
        Observer mother=new Mother();

        XiaoMing xiaoMing=new XiaoMing();
        xiaoMing.addObserver(father);
        xiaoMing.addObserver(mother);

        xiaoMing.eat();
        xiaoMing.run();

    }
}
小明吃饭了。。。开始通知观察者
母亲观察到小明有变化:小明吃饭了
父亲观察到小明有变化:小明吃饭了
小明跑步了。。。开始通知观察者
母亲观察到小明有变化:小明跑步了
父亲观察到小明有变化:小明跑步了

个人博客:http://www.whereta.com

你可能感兴趣的:(观察者模式)