一,概念
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。观察者模式多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。
二,例子
四个要素
抽象被观察者(Subject):被观察的对象的接口。包含操作规范。
具体被观察者(ConcreteSubject):被观察者的具体实现。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。具体被观察者需要维持(添加,删除,通知)一个观察者对象的队列列表。
抽象观察者(Observer):接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
具体观察者(ConcreteObserver):观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
例子1:使用java.util包下的Observable,Observer实现观察者模式
实体类:Blog
/** * * @类名称:Blog * @类描述:实体类 * @创建人:zender */ public class Blog { private String title; private String content; public Blog(String title, String content) { this.title = title; this.content = content; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
被观察者:BlogSubject
setChange()方法用来设置一个内部标志位注明数据发生了变化;
notifyObservers()方法会去调用观察者对象列表中所有的Observer的update()方法,通知它们数据发生了变化。
只有在setChange()被调用后,notifyObservers()才会去调用update()。
/** * * @类名称:BlogSubject * @类描述:被观察者 * @创建人:zender */ public class BlogSubject extends Observable{ public void publishBlog(String title,String content){ Blog b = new Blog(title,content); System.out.println("博主:发表新文章,文章标题:" + title + ",文章内容:" + content); //setChanged方法标志着该对象更变。 hasChanged方法返回true。 this.setChanged(); //notifyObservers()方法会去调用一个列表中所有的Observer的update()方法,通知它们数据发生了变化。 this.notifyObservers(b); } }
观察者:BlogObserverOne,BlogObserverTwo
方法:update(Observable o, Object arg)
形参Object arg,对应一个由notifyObservers(Object arg);传递来的参数,当执行的是notifyObservers();时,arg为null。
/** * * @类名称:BlogObserverOne * @类描述:观察者1 * @创建人:zender */ public class BlogObserverOne implements Observer{ @Override public void update(Observable o, Object arg) { Blog b = (Blog) arg; System.out.print("BlogObserverOne:博主发表了新的文章:"); System.out.print("标题为:“" + b.getTitle() +"”"); System.out.println(",内容为:“" + b.getContent()+ "”"); } }
/** * * @类名称:BlogObserverTwo * @类描述:观察者2 * @创建人:zender */ public class BlogObserverTwo implements Observer{ @Override public void update(Observable o, Object arg) { Blog b = (Blog) arg; System.out.print("BlogObserverTwo:博主发表了新的文章:"); System.out.print("标题为:“" + b.getTitle() +"”"); System.out.println(",内容为:“" + b.getContent()+ "”"); } }
测试:
/** * * @类名称:Test * @类描述:测试 * @创建人:zender */ public class Test { public static void main(String[] args) { BlogSubject cs = new BlogSubject(); BlogObserverOne one = new BlogObserverOne(); BlogObserverTwo two = new BlogObserverTwo(); cs.addObserver(one); cs.addObserver(two); cs.publishBlog("内容1","这是我写的内容1"); //移除订阅者1 cs.deleteObserver(one); System.out.println("----------------"); cs.publishBlog("文章2", "这是我写的内容2"); } }
结果:
例子2:手动实现观察者模式
抽象观察者(ObServer):MyObserver
/** * * @类名称:MyObserver * @类描述:抽象观察者(ObServer) * @创建人:zender */ public interface MyObServer { public void update(String message); }
具体观察者(ConcrereObserver):BlogUser
/** * * @类名称:BlogUser * @类描述:具体观察者(ConcrereObserver) * @创建人:zender */ public class BlogUser implements MyObServer { //博客用户名称 private String name; public BlogUser(String name) { super(); this.name = name; } @Override public void update(String message) { System.out.println(name + "您关注的博客更新了:" + message); } }
抽象被观察者(Subject):MySubject
/** * * @类名称:MySubject * @类描述:抽象被观察者(Subject) * @创建人:zender */ public interface MySubject { /** * 增加订阅者 */ public void attach(MyObServer observer); /** * 删除订阅者 */ public void detach(MyObServer observer); /** * 通知订阅者更新消息 */ public void notify(String message); }
具体被观察者(ConcreteSubject):BlogSubject
/** * * @类名称:BlogSubject * @类描述:具体被观察者(ConcreteSubject) * @创建人:zender */ public class BlogSubject implements MySubject{ //存储订阅者的List private List<MyObServer> blogUserList = new ArrayList<MyObServer>(); @Override public void attach(MyObServer observer) {//添加订阅者 blogUserList.add(observer); } @Override public void detach(MyObServer observer) {//删除订阅者 blogUserList.remove(observer); } @Override public void notify(String message) {//循环通知订阅者 for (MyObServer myObServer : blogUserList) { myObServer.update(message); } } }
测试:
/** * * @类名称:Test * @类描述:测试类 * @创建人:zender */ public class Test { public static void main(String[] args) { BlogSubject bs = new BlogSubject(); //1,创建用户 BlogUser user1 = new BlogUser("张三"); BlogUser user2 = new BlogUser("李四"); BlogUser user3 = new BlogUser("王伟"); //2,订阅Blog bs.attach(user1); bs.attach(user2); bs.attach(user3); //3,发布Blog bs.notify("zender-Blog更新了。"); System.out.println("--------------------"); //移除订阅者 bs.detach(user3); bs.notify("zender-Blog又更新了。"); } }
结果:
三、观察者模式的典型应用
1,侦听事件驱动程序设计中的外部事件。
2,侦听/监视某个对象的状态变化。
3,发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者。