先来领会一下观察者模式的精神:
观察者模式定义了一系列对象之间一对多的关系。通俗的比喻相当于报社和订报的人,水电局和用户。也就是出版者和订阅者。
观察者模式涉及到了如下几点定义:
抽象主题角色
具体主题角色
抽象观察者角色
具体观察者角色
1.接下来是具体的例子
就拿某直播平台的通知功能来说,其类图如下:(Tuhao就是土豪)

假设游戏是一个大的主题,在这里它相当于一个抽象主题角色:
public interface Game {
    void addPeople(People people);
    void removePeople(People people);
    void notifyPeople();
}
抽象主题角色最基本具有添加,移除以及通知观察者的功能
然后是具体主题角色,例如在游戏分类下的StarCraft就是其中的一个游戏(具体主题角色):
public class StarCraft implements Game {
    private ArrayList<People> viewer;
    private String message;
    public StarCraft() {
        viewer = new ArrayList<People>();
    }
    public void addPeople(People people) {
        viewer.add(people);
    }
    public void removePeople(People people) {
        if (viewer.contains(people)) {
            viewer.remove(people);
        } else {
            System.out.println("No viewers!");
        }
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public void notifyPeople() {
        for (People people : viewer) {
            people.update(message);
        }
    }
}
它维护着该主题下的用户(观察者)列表,负责移除,添加观察者,发送通知等一系列操作。
接下来就是抽象观察者角色了:
public interface People {
    void update(String message);
}
最后就是具体观察者角色,例如上斗鱼看直播的土豪:
public class Tuhao implements People {
    public void update(String message) {
        System.out.println("Watch: " + message+" and send money!");
    }
}
最后就是测试了:
斗鱼某主播上开了直播,然后系统会通知订阅该直播的人直播开始了。
测试:
    @Test
    public void test() {
        StarCraft starCraft = new StarCraft();
        starCraft.setMessage("干死黄旭东!");
        //土豪mike
        Tuhao mike = new Tuhao();
        starCraft.addPeople(mike);
        starCraft.notifyPeople();
    }
//Watch: 干死黄旭东! and send money!
2.在Java JDK中,自带有java.util.Observable以及Observer分别为抽象主题角色以及抽象观察者角色。
使用它们改写观察者的关系如下:

Observable默认使用Vector保存期观察者,且对其中的大部分方法都加了synchronized进行同步。不过,Observable是个类,继承了它就不能继承其他的类了。
此外,还增加了changed标志,只有当changed标志为true的时候,通知才可进行,且通知完成后,会将标志重置为false:
其代码如下:
public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;
    public Observable() {
        obs = new Vector<>();
    }
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    public void notifyObservers() {
        notifyObservers(null);
    }
    public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;
        synchronized (this) {
           
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }
    protected synchronized void setChanged() {
        changed = true;
    }
    protected synchronized void clearChanged() {
        changed = false;
    }
    public synchronized boolean hasChanged() {
        return changed;
    }
    public synchronized int countObservers() {
        return obs.size();
    }
}
具体主题:
public class StarCraft extends Observable {
    public void setChanged(){//Observable的setChanged为protected,必须在主题实现中实现
        super.setChanged();
    }
}
具体观察者:
public class Tuhao implements Observer{
    public void update(Observable o, Object arg) {
        System.out.println("土豪 online!");
        if(arg!=null){
            System.out.println(arg.toString());
        }
    }
}
测试:
    @Test
    public void test1(){
        StarCraft starCraft = new StarCraft();
        Tuhao mike = new Tuhao();
        starCraft.addObserver(mike);
        //可以查看状态是否改变
        boolean status = starCraft.hasChanged();
        System.out.println("状态是否改变:"+status);
        starCraft.notifyObservers();
        //可以查看共有多少待通知的对象
        System.out.println("将通知人数为:"+starCraft.countObservers());
        //改变状态,这里是重写了Observable的setChanged方法
        starCraft.setChanged();
        status = starCraft.hasChanged();
        System.out.println("状态是否改变:"+status);
        starCraft.notifyObservers();
        System.out.println("通知人数为:"+starCraft.countObservers());
        //通知完之后,状态会恢复原样,即为false,等待下一次需要状态的改变
        status = starCraft.hasChanged();
        System.out.println("状态是否改变:"+status);
    }
//    状态是否改变:false
//    将通知人数为:1
//    状态是否改变:true
//    土豪 online!
//    通知人数为:1
//    状态是否改变:false
此外,还可以调用:
        starCraft.notifyObservers("额外信息");
方法传递额外的信息。
3.最后,在Java GUI中,监听器的添加使用的就是观察者模式:
        JButton j = new JButton();
        j.addActionListener(new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("got it!");
            }
        });
监听器的实现类(上面的匿名内部类)就是观察者,JButton就是主题。
如上:)
参考资料:
Head First 设计模式
原文:http://www.cnblogs.com/zhangxd-stn/p/dp2.html