一:观察者模式定义
1.1 定义
观察者模式定义了对象间的一对多关系,当一个对象的行为发生变化时,订阅者能够收到相应的通知,其又称为发布/订阅模式。观察者模式一般有2种,一种推模式,一个拉模式,推模式即当被订阅者对象发生行为改变时,会主动将变化的消息推给订阅者,而不考虑每个订阅者当时的处理能力,另一种比较好的是拉模式,即订阅者持有被观察者的实例,当被订阅者的行为发生改变时,拉模式会主动的根据引用获取变化的相关数据。
1.2 角色
被观察者:抽象观察者接口,包括观察者的注册,删除,通知等方法。
观察者 :定义观察者对象。
抽象观察者:定义观察者通用接口,当监听的被观察者发现行为改变时,动态的实现相应的行为动作。
具体观察者:定义具体的观察者对象
1.3 使用场景
1:当一个系统中某个对象的改变需要同时改变其他对象的时候
2:当一个抽象模型中,其中一方面依赖于另一方面,需要分别封装到独立的对象中时,彼此独立于抽象模型中。
二:观察者模式实现
2.1 产品接口,要通知什么?订阅什么?
import java.util.List; //产品接口,发布者要发布什么给订阅者?,订阅者要订阅什么? 这中间需要一个产品对象 public interface Product { //添加产品 void addProduct(String name); //获取所有产品 List<String> getProducts(); }
2.2 被观察者
//发布者 public interface Publisher { //添加订阅者 void addSubScribe(SubScribe subscribe); //移除订阅者 void removeSubScribe(SubScribe subscribe); //发布者通知所有的订阅者 void notifyAllSubScribe(); }
2.3 抽象被观察者
//抽象的被观察者 public abstract class AbstractPublisher implements Product,Publisher { private List<SubScribe> subs = Collections.synchronizedList(new ArrayList<SubScribe>()); @Override public void addSubScribe(SubScribe subscribe) { if(subs.contains(subscribe)){ System.out.println("已经存在这个订阅者,不需要重新注册"); }else{ subs.add(subscribe); } } @Override public void removeSubScribe(SubScribe subscribe) { if(null == subscribe || !subs.contains(subscribe)){ System.out.println("不存在这个订阅者,不需要"); }else{ subs.remove(subscribe); } } @Override public void notifyAllSubScribe() { synchronized (subs) { for(final SubScribe subScribe : subs){ //订阅者接收通知,接收到的是一个product产品对象 subScribe.receive(this); } } } }
2.4 观察者接口
public interface SubScribe { //订阅者订阅产品 void receive(Product product); }
2.5 抽象观察者实现
//抽象的观察者 public abstract class AbstractSubscribe implements SubScribe { private String name; public AbstractSubscribe(String name) { this.name = name; } protected void printProducts(List<String> products) { if (null != products && products.size() > 0) { for (String st : products) { System.out.println("产品:" + st); } } } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2.6 被观察者实现
//被观察者具体实现 public class ProductPublisher extends AbstractPublisher { private List<String> products = new ArrayList<String>(); //发布者每次添加一个产品都需要通知所有的订阅者 @Override public void addProduct(String name) { products.add(name); super.notifyAllSubScribe(); } @Override public List<String> getProducts() { return products; } }
2.7 观察者实现
//产品订阅,订阅者订阅的是产品 public class ProductSubscribe extends AbstractSubscribe{ public ProductSubscribe(String name) { super(name); } @Override public void receive(Product product) { System.out.println("订阅者:"+super.getName()+" 收到发布者消息,产品列表为"); for(String st : product.getProducts()){ System.out.println(st); } } }
2.8 测试类
public class ObserverTest { public static void main(String[] args) { AbstractPublisher abstractPublisher = new ProductPublisher(); abstractPublisher.addSubScribe(new ProductSubscribe("重庆程序员")); abstractPublisher.addSubScribe(new ProductSubscribe("北京程序员")); abstractPublisher.addSubScribe(new ProductSubscribe("广州程序员")); abstractPublisher.addProduct("重庆程序员使用戴尔笔记本电脑"); abstractPublisher.addProduct("北京程序员使用惠普笔记本电脑"); abstractPublisher.addProduct("广州程序员使用三星笔记本电脑"); } }
2.9 实现效果
订阅者:重庆程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 订阅者:北京程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 订阅者:广州程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 订阅者:重庆程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 订阅者:北京程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 订阅者:广州程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 订阅者:重庆程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 广州程序员使用三星笔记本电脑 订阅者:北京程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 广州程序员使用三星笔记本电脑 订阅者:广州程序员 收到发布者消息,产品列表为 重庆程序员使用戴尔笔记本电脑 北京程序员使用惠普笔记本电脑 广州程序员使用三星笔记本电脑