观察者模式的定义:
观察者模式定义了一种一对多的依赖关系,被观察者一般称为主题,一个主题对象会有多个观察者,一旦主题更新了信息,就会推送到各个观察者处。
举一个生活中常见的例子:
3个人(观察者)都想买房(主题对象),于是他们都订阅了某楼盘的房价信息,一旦楼盘的房价变动,这3个人都会受到最新的房价。这就是观察者模式的作用。
其实Java中,已经内置有实现观察者模式的api。但我们先来自己实现观察者模式。
自行实现观察者模式
观察者模式的组成
-
抽象主题角色:抽象主题提供一个接口,可以增加和删除观察者角色。
-
具体主题角色:当具体主题内部的信息更新时,通知所有注册的观察者,使他们收到消息
-
抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
-
具体观察者角色:该角色实现抽象观察者角色所要求的更新接口。
下面是具体的实例(该实例以购房为情景)
首先看工程目录图:
抽象主题角色:
public interface Subject {
// 添加主题(被观察者)
public void addObserver(Observer observer);
// 移除主题(被观察者)
public void removeObserver(Observer observer);
// 更新所有观察者
public void notifyObserver();
}
具体主题角色:
public class House implements Subject {
private List<Observer> observers = new ArrayList<>();
private float price;
public House(float price){
this.price = price;
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver() {
if(observers != null){
for(Observer observer : observers){
observer.update(price);
}
}
}
public void updatePrice(float price){
this.price = price;
notifyObserver();
}
public String toString(){
return "房价为:" + price;
}
}
抽象观察者角色:
public interface Observer {
public void update(float price);
}
具体观察者角色:
public class HouseObserver implements Observer{
private String observerName;
//为不同的房子价格观察者记录名字
public HouseObserver(String observerName){
this.observerName= observerName;
}
@Override
public void update(float currentPrice) {
System.out.println( observerName+ " 观察到当前的价格为:" + currentPrice);
}
}
测试代码
public class testObserver {
public static void main(String args[]){
//设置初始价格
House house = new House(10000);
HouseObserver observer1 = new HouseObserver("买房者A");
HouseObserver observer2 = new HouseObserver("买房者B");
HouseObserver observer3 = new HouseObserver("买房者C");
//加入观察者观察房价
house.addObserver(observer1);
house.addObserver(observer2);
house.addObserver(observer3);
//初始房价
System.out.println(house);
//更新房价
house.updatePrice(6666);
//更新后房价
System.out.println(house);
}
}
下面是运行的结果:
房价为:10000.0
买房者A 观察到当前的价格为:6666.0
买房者B 观察到当前的价格为:6666.0
买房者C 观察到当前的价格为:6666.0
房价为:6666.0
具体的解释都在代码中,也不一一解释了。
关键在于 —–> house.updatePrice(6666) 主题更新,每一个买房者都接收到了通知,并且打印了出来。
Java内置观察者模式
Java中提供了一个Observerable类和Observer接口,这两个类就相当于上面所提到的 抽象主题角色 和 抽象观察者角色。
需要注意的地方:
- Observerable是一个类,Observer是一个接口,所有具体主题角色都要继承Observerable,所有juice观察者角色都要实现Observer接口。
- 具体主题角色信息改变了,它必须调用setChanged()方法。
- 具体主题角色准备通知观测程序它的改变时,它必须调用notifyObservers()方法,这导致了在观测对象中对update()方法的调用。
下面来看具体的实例(也是基于购房实例)
工程结构:
具体主题角色:
public class House extends Observable {
private float price;
public House(float price) {
this.price = price;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
// 标记已经变化
super.setChanged();
// 设这价格被改变
super.notifyObservers(price);
// 更新价格
this.price = price;
}
public String toString() {
return "房价为:" + price;
}
}
具体观察者角色:
public class HouseObserver implements Observer {
private String houseName;
// 为不同的房子价格观察者记录名字
public HouseObserver(String houseName) {
this.houseName = houseName;
}
@Override
public void update(Observable subject, Object price) {
if (price instanceof Float) {
float currentPrice = (Float) price;
System.out.println(houseName + " 观察到当前的价格为:" + currentPrice);
}
}
}
测试代码
public class testObserver {
public static void main(String args[]) {
// 设置初始价格
House house = new House(10000);
HouseObserver observer1 = new HouseObserver("买房者A");
HouseObserver observer2 = new HouseObserver("买房者B");
HouseObserver observer3 = new HouseObserver("买房者C");
// 加入观察者观察房价
house.addObserver(observer1);
house.addObserver(observer2);
house.addObserver(observer3);
// 初始房价
System.out.println(house);
// 更新房价
house.setPrice(6666);
// 更新后房价
System.out.println(house);
}
}
运行结果如下:
房价为:10000.0
买房者C 观察到当前的价格为:6666.0
买房者B 观察到当前的价格为:6666.0
买房者A 观察到当前的价格为:6666.0
房价为:6666.0
说明观察者模式确实起到了作用。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/7810.html