设计模式之观察者模式

观察者设计模式

  定义了对象之间一对多的关系。当一个对象的状态发生变化,它所有的依赖者会收到更新通知,并作出相应的变化。

相关对象

  主题(Subject):主题是一个接口,接口规定了具体主题需要实现的方法,如添加、删除观察者以及通知观察者更新数据的方法;

  观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更细数据的方法;

  具体主题(ConcreteSubject):是实现主题接口的一个实例;

  具体观察者(ConcreteObserver):是实现观察者接口的一个实例;

  

使用场景

  (1)聊天室程序:一个人发送一条消息给服务器,服务器会将该消息广播给聊天室内的其他人;

  (2)邮件订阅:多人订阅了《NBA》这个相关消息,当有新消息出现的时候,通过广播给所有订阅的人;

  (3)Servlet中,监听器的实现

测试实例

  (1)观察者

/**
 * Observer 抽象的观察者
 * @author yangkj
 */
public interface Observer {

    void update(Subject subject);
}

  (2)主题

/**
 * 
 * <p>
 * Subject 主题
 * <p>
 * 
 * @author <a href="mailto:yangkj@corp.21cn.com">yangkj</a>
 * @version
 * @since 2016年9月26日
 */
public abstract class Subject {
    /**
     * 观察者列表
     */
    private List<Observer> list = new ArrayList<>();

    /**
     * 添加观察者
     */
    public void registerOberver(Observer obs) {
        list.add(obs);
    }

    /**
     * 删除观察者
     */
    public void removerOberver(Observer obs) {
        list.remove(obs);
    }

    /**
     * 通知所有的观察者更新
     */
    public void noticeAllObserver() {
        for (Observer obs : list) {
            obs.update(this);
        }
    }
}

  (3)具体主题

/**
 * ConcreteSubject 具体的主题
 * @author yangkj*/
public class ConcreteSubject extends Subject {
    
    private int status;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
        //主题对象值发生变化,通知所有观察者,进行状态值变化
        this.noticeAllObserver();
    }
}

  (4)具体观察者

/**
 * ConcreteObserver 具体的观察者
 * @author yangkj*/
public class ConcreteObserver implements Observer {

    private int status;

    @Override
    public void update(Subject subject) {

        status = ((ConcreteSubject) subject).getStatus();

        System.out.println("广播通知,状态值发生变化为:" + status);
    }

    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }
}

  (5)测试代码

public class Client {

    public static void main(String[] args) {
        // 新建两个观察者
        Observer obsA = new ConcreteObserver();
        Observer obsB = new ConcreteObserver();
        // 定义目标对象
        ConcreteSubject sub = new ConcreteSubject();
        sub.registerOberver(obsA);
        sub.registerOberver(obsB);
        sub.setStatus(0);
        /**
         * 添加一个观察者
         */
        Observer obsC = new ConcreteObserver();
        sub.registerOberver(obsC);
        sub.setStatus(1);
        /**
         * 移除一个观察者
         */
        sub.removerOberver(obsB);
        sub.setStatus(10);
    }
}

  测试结果


  

  当然我们自己实现的是有缺陷的,比如没有考虑并发同步的问题;在Java.util中已经为我们提供了相关的工具类,下面我们用这些工具类完成一个观察者设计模式。

利用java.util.Observable和java.util.Observer实现观察者模式

  (1)观察者

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

/**
 * ConcreteObserver 观察者
 * 
 * @author yangkj
 */
public class ConcreteObserver implements Observer {

    private int status;

    @Override
    public void update(Observable o, Object arg) {
        status = ((ConcreteSubject) o).getStatus();
        System.out.println("广播通知,状态值变化为:" + status);
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}

  (2)主题

import java.util.Observable;
/**
 * ConcreteObserver 具体的主题
 * 
 * @author yangkj
 */
public class ConcreteSubject extends Observable{

    private int status;

    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
        //表示目标状态已经做了修改
        setChanged();
        //通知所有的观察者,并且将具体的状态值进行传递
        notifyObservers(status);
    }
}

  (3)测试代码

public class Client {

    public static void main(String[] args) {
        Observer obs1 = new ConcreteObserver();
        Observer obs2 = new ConcreteObserver();
        Observer obs3 = new ConcreteObserver();
        
        ConcreteSubject sub = new ConcreteSubject();
        sub.addObserver(obs1);
        sub.addObserver(obs2);
        sub.addObserver(obs3);
        sub.setStatus(20);
        
        System.out.println("广播者个数:"+sub.countObservers());
        
        sub.deleteObserver(obs3);
        System.out.println("广播者个数:"+sub.countObservers());
    }
}

  测试结果

  

原文地址:https://www.cnblogs.com/parryyang/p/5909503.html