一 观察者模式
观察者模式:针对于对象之间存在一对多的关系,当一的一方的状态发生改变的时候,通知多的那一方,一的那一方可以称作为主题,然后多的那一方便是订阅者。
举个例子:就像是一个微信公众号,每天会有消息推送的功能,有很多人去关注了,公众号就会向那些关注了的人发送消息,一旦取消订阅,这个公众号便不会再去向这个订阅者发送消息了。
由此可知,观察者模式主题一共包含两大部分,主题和订阅者。
主题:有三个主要的方法,分别是订阅,解除订阅,发布这3个功能。
订阅者: 接收主题推送过来的消息。
二 观察者模式代码示例如下
代码思路:
2.1 先定义一个主题的接口(为什么要定义这个接口?1:接口可以多实现比较灵活,2:接口定义了规范,体现在这个接口里面定义的方法,那么子类就必须按照接口定义的方法规范来实现,如方法名,参数列表,返回值等),定义主题接口的3个方法:订阅,解除订阅,发布。代码示例:
import java.util.List;
public interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObserver(List<Observer> observers);
}
2.2 根据业务需求定义这个主题类,来实现这个接口,同时定义一个发布消息的方法。这里我定义的是一个微信公众号的类。代码示例如下:
import java.util.ArrayList;
import java.util.List;
public class WeixinPublicSubject implements Subject{
String message = null;
private List<Observer> observers = null;
@Override
public void registerObserver(Observer observer) {
if(observers == null){
observers = new ArrayList<Observer>();
}
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(observers != null && observers.indexOf(observer) >= 0){
observers.remove(observers.indexOf(observer));
}
}
@Override
public void notifyObserver(List<Observer> observers) {
if(observers !=null && observers.size() > 0){
for(int i=0; i<observers.size(); i++){
observers.get(i).update(message);
}
}
}
public void updateMessage(String message){
this.message = message;
notifyObserver(observers);
}
}
2.3 定义一个订阅者的接口,有很多的发布者,那么所有的订阅者都要实现这个接口。
public interface Observer {
public void update(String message);
}
2.4 定义一个展示的接口,里面定义一个展示的方法,然后再定义两个实现类,一个是对外展示的类,一个是不展示的类(这里面涉及到的是一个策略模式,如果是单纯的观察者模式的话可以不做定义)。
public interface Displayment {
public void display(String message);
}
public class DoDiplayment implements Displayment{
@Override
public void display(String message) {
System.out.println("我收到了消息,消息是:"+message);
}
}
public class NotDisplayment implements Displayment{
@Override
public void display(String message) {
System.out.println("我收到了消息,但是我不同享");
}
}
2.5 定义一些订阅者类实现订阅者这个接口。这里我定义的是ZhangSan和Lisi这两个订阅者,
代码示例如下:
public class ZhangSan implements Observer {
private Displayment displayment;
public ZhangSan(){
displayment = new DoDiplayment();
}
@Override
public void update(String message) {
// TODO Auto-generated method stub
System.out.println("我是张三,消息是:"+ message);
displayment.display("我是张三,"+message);
}
}
public class Lisi implements Observer{
private Displayment displayment;
public Lisi(){
displayment = new NotDisplayment();
}
@Override
public void update(String message) {
// TODO Auto-generated method stub
System.out.println("我是李四, 消息是:"+ message);
displayment.display("我是李四,"+message);
}
}
2.6 订阅者类根据自己的想法定义是否对外展示的类(策略模式的体现)
2.7 订阅者去订阅这个主题。主题推送消息。测试代码如下:
public class Test {
public static void main(String[] args){
WeixinPublicSubject wps = new WeixinPublicSubject();
ZhangSan zhangsan = new ZhangSan();
Lisi lisi = new Lisi();
wps.registerObserver(zhangsan);
wps.registerObserver(lisi);
wps.updateMessage("今天下午两点开会");
wps.removeObserver(zhangsan);
wps.updateMessage("今天下午三点开会");
}
}
输出结果如下:
我是张三,消息是:今天下午两点开会
我收到了消息,消息是:我是张三,今天下午两点开会
我是李四, 消息是:今天下午两点开会
我收到了消息,但是我不同享
我是李四, 消息是:今天下午三点开会
我收到了消息,但是我不同享
三 观察者模式总结
观察者模式实现了主题与订阅者之间的解耦,为什么这么说?因为观察者无需知道订阅者具体是什么样的订阅者,不管你是zhangsan,lisi,wangwu。主要订阅了这个主题,就会发送通知,如果没有订阅这个主题,那么便不会收到主题推送的通知。在这种模式之下,大大增加了代码的可扩展性,以后有其它的主题,只需要实现主题接口,而不需要去修改原来的代码,同理,如果有新的订阅者,也只需要实现订阅者的接口,然后到对应的主题上注册即可。