1. 定义
定义了对象之间一对多依赖,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。
观察者依赖于主题,只要主题状态一有变化,观察者就会被通知。
观察者是一种行为型模式。
2. 类图
类图说明:
- 对象使用主题接口将自己注册为观察者,或者把自己从观察者中删除。
- 一个具体的主体总是实现主体接口,除了注册和删除方法之外,还实现了 notifyObservers()方法,此方法用于在状态改变时更新所有观察者。
- 具体主题也可能有设置和获取状态的方法。
- 每个主题可以有多个观察者。
- 所有的观察者必须实现观察者接口,这个接口只有update()一个方法,当主题状态改变时他被调用。
- 具体的观察者可以是实现观察者接口的任意类。观察者必须注册具体类,以便接受更新。
3. 应用
实现一个简单的账单显示,账单面板BillPanel中可以添加删除账单Bill,有两个观察者面板,一个时TotalMoneyPanel用来显示总金额,一个时InterestMoneyPanel用来显示利息。当BillPanel中添加账单和删除账单时,就会通知观察者,显示总金额和利息的面板就会自动更新。
类图
代码
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
public interface Observer {
void update(double moneyChange);
}
public class Bill {
private String name;
private double money;
Bill(String name, double money) {
this.name=name;
this.money=money;
}
double getMoney() {
return money;
}
}
public class BillPanel implements Subject{
private List<Bill> bills;
private List<Observer> observers;
public BillPanel() {
this.bills=new ArrayList<>();
this.observers=new ArrayList<>();
}
public void addBill(Bill bill){
bills.add(bill);
notifyObservers();
}
public void removeBill(Bill bill){
bills.remove(bill);
notifyObservers();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
double totalMoney= bills.stream().mapToDouble(Bill::getMoney).sum();
observers.forEach(observer -> observer.update(totalMoney));
}
}
public class InterestMoneyPanel implements Observer {
private Subject subject;
private double interestMoney;
public InterestMoneyPanel(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void update(double moneyChange) {
this.interestMoney = moneyChange;
display();
}
private void display() {
System.out.println("利息是: " + interestMoney * 0.04);
}
}
public class TotalMoneyPanel implements Observer{
private double totalMoney;
private Subject subject;
public TotalMoneyPanel(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void update(double moneyChange) {
this.totalMoney=moneyChange;
display();
}
public void display(){
System.out.println("总金额:"+totalMoney);
}
}
public class Test {
public static void main(String[] args) {
//主题
BillPanel billPanel=new BillPanel();
//观察者
InterestMoneyPanel interestMoneyPanel=new InterestMoneyPanel(billPanel);
TotalMoneyPanel totalMoneyPanel=new TotalMoneyPanel(billPanel);
Bill bill1=new Bill("1",200);
Bill bill2=new Bill("2",300);
Bill bill3=new Bill("3",100);
billPanel.addBill(bill1);
billPanel.addBill(bill2);
billPanel.addBill(bill3);
billPanel.removeBill(bill2);
}
}