观察者模式
1.定义 (自己面试说了观察者模式,但是问起来被问住两次,不总结不行)
在对象之间定义了一对多的依赖,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
2.实现
2.1定义观察者接口
public interface Observer { public void update(String message); }
包含了收到通知后执行的操作.
2.2定义被观察者接口
public interface Observerable { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); }
包含注册,删除,通知等功能.
2.3实现具体的观察者
public class User implements Observer{ private String name; private String message; public User(String name) { super(); this.name = name; } @Override public void update(String message) { this.message = message; read(); } public void read() { System.out.println(name+" 收到 " + message); } }
2.4实现具体的被观察者
package observer3; import java.util.ArrayList; import java.util.List; public class WechatServer implements Observerable{ private List<Observer> list; private String message; public WechatServer() { list = new ArrayList<>(); } @Override public void registerObserver(Observer o) { list.add(o); } @Override public void removeObserver(Observer o) { if (!list.isEmpty()) { list.remove(o); } } @Override public void notifyObserver() { for (Observer o : list) { o.update(message); } } public void setInformation(String s) { this.message = s; System.out.println("通知者发送:"+s); notifyObserver(); } }
以微信的公众号通知为例子,里面包含了list接口,可以通过 setInformation 方法遍历list来通知观察者.
3.测试
public class TestObserver { public static void main(String[] args) { WechatServer observerable = new WechatServer(); Observer ob1 = new User("ob1"); Observer ob2 = new User("ob2"); Observer ob3 = new User("ob3"); Observer ob4 = new User("ob4"); observerable.registerObserver(ob1); observerable.registerObserver(ob2); observerable.registerObserver(ob3); observerable.registerObserver(ob4); observerable.setInformation("hello world"); } }
被问到的两个面试题:
1.观察者模式是什么?
存在观察者和被观察者两个对象,两者是一对多的关系,当被观察者发出通知的时候,观察者可以收到通知并执行相应的操作.
实现是通过定义 观察者 和 被观察者两个接口, 被观察者 可以注册和删除 观察者,在实现类里面这个是通过list接口实现的, 通过遍历list 集合来调用观察者的方法来通知.
2.什么时候应该通知观察者?
在观察者实现类中的属性改变的时候或者根据具体需求定义的方法来调用notify方法通知.
需要结合具体需求.
3.在添加新的观察者的时候不需要修改被观察者(主题)的代码,直接调用register方法即可注册,实现无侵入式编程.