观察者设计模式
定义了对象之间一对多的关系。当一个对象的状态发生变化,它所有的依赖者会收到更新通知,并作出相应的变化。
相关对象
主题(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()); } }
测试结果