概括
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖他的对象都得到通知并被自动更新。
概述
在许多设计中,经常涉及多个对象都对一个特殊对象中的数据变化感兴趣,而且着多个对象都希望跟踪那个特殊对象中的数据变化。例如,某些需找工作的人对”求职中心”的职位需求信息的变化非常关心,
观察者模式是关于多个对象想知道一个对象中数据变化情况的一种成熟的模式。观察者模式中有一个称作”主题”的对象和若干个称作”观察者”的对象,”主题”和”观察者”是一对多的依赖关系,当”主题”的状态发生变化时,所有”观察者”都收到通知。
UML类图
观察者模式中的四种角色
主题(subject):主题是一个接口,该接口规定了具体主题需要实现的方法
观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法
具体主题(Concrete):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合来存放观察者的引用,以便数据变化时通知具体观察者。
具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题的引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为该主题的观察者 ;或在主题的观察者集合中删除自己 是自己不再是该主题的观察者。
观察者模式中的“”推“”数据 和“”拉“”数据
推数据方式
推数据方式是指具体主题将变化后的数据全部交给具体观察者。当具体主题认为具体观察者需要这些变换后的全部数据时往往采用推数据方式。拉数据方式
拉数据方式是指具体主题不将变化后的数据交给具体观察者,而是提供了获得这些数据的方法,具体观察者在得到通知后,可以调用具体主题得到数据(观察者自己将数据“”拉“”过来),但需要自己判断数据是否发生变化。当具体主题不知道具体观察者是否需要这些变换后的数据时往往采用拉数据方式。
适用场景
当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
应用: A ,B都是一家超市的常客
顾客A 对打折商品名字感兴趣 顾客B对打折商品价格感兴趣
(拉数据)
subject.java
public interface Subject {
public void addObserver(Observer o);
public void deleteObserver(Observer o);
public void notifyObservers();
}
Observer.java
public interface Observer {
public void update();
}
ShopSubject.java
public class ShopSubject implements Subject{
String goodsName;
double oldPrice,newPrice;
ArrayList<Observer> customerList;
ShopSubject(){
customerList = new ArrayList<Observer>();
}
@Override
public void addObserver(Observer o) {
// TODO Auto-generated method stub
if(!(customerList.contains(o)))
customerList.add(o);
}
@Override
public void deleteObserver(Observer o) {
// TODO Auto-generated method stub
if(!(customerList.contains(o)))
customerList.remove(o);
}
@Override
public void notifyObservers() {
// TODO Auto-generated method stub
for(int i = 0 ; i < customerList.size() ; i++){
Observer observer = customerList.get(i);
observer.update();
}
}
//添加商品
public void setGoods(String name, double oldP, double newP){
goodsName = name;
oldPrice = oldP;
newPrice = newP;
notifyObservers();
}
public String getGoodsName() {
// TODO Auto-generated method stub
return goodsName;
}
public double getOldPrice() {
// TODO Auto-generated method stub
return oldPrice;
}
public double getNewprice() {
// TODO Auto-generated method stub
return newPrice;
}
}
CustomerOne.java
public class CustomerOne implements Observer{
Subject subject;
String goodsName,personName;
CustomerOne(Subject subject,String name){
this.subject = subject;
this.personName = name;
subject.addObserver(this);
}
@Override
public void update() {
// TODO Auto-generated method stub
if(subject instanceof ShopSubject){
goodsName = ((ShopSubject)subject).getGoodsName();
System.out.println("我是" + personName + " 只对打折商品的名字感兴趣");
System.out.println(goodsName);
}
}
}
CustomerTwo.java
public class CustomerTwo implements Observer{
Subject subject;
String personName;
double oldPrice,newPrice;
CustomerTwo(Subject subject,String name){
this.subject = subject;
personName = name;
subject.addObserver(this);
}
@Override
public void update() {
// TODO Auto-generated method stub
if(subject instanceof ShopSubject){
oldPrice = ((ShopSubject)subject).getOldPrice();
newPrice = ((ShopSubject)subject).getNewprice();
System.out.println("我是" + personName + " 只对降价商品价格感兴趣");
System.out.println("原价:" + oldPrice + " 现价:" + newPrice);
}
}
}
Test.java
public class Test {
public static void main(String [] args){
ShopSubject shopSubject = new ShopSubject();
CustomerOne customerOne = new CustomerOne(shopSubject, "Tom");
CustomerTwo customerTwo = new CustomerTwo(shopSubject, "Jack");
shopSubject.setGoods("皮皮虾", 3.0, 2.65);
}
}
运行结果:
我是Tom 只对打折商品的名字感兴趣
皮皮虾
我是Jack 只对降价商品价格感兴趣
原价:3.0 现价:2.65