2011年12月25日日曜日

[设计模式] 观察者模式 (Observer)

1. 场景
观察者模式定义了对象间的一对多依赖关系, 让一个或多个观察者对象观察一个主题对象
当主题对象的状态发生变化时, 系统能通知所有的依赖于此对象的观察者对象, 从而使得观察者对象能够自动更新
实际上, 完全可以把观察者接口理解成事件监听接口, 而被观察者对象也可当成事件源来处理, Java 事件机制的底层实现, 本身就是通过观察者模式来实现的

2. 角色
Subject: 主题
Observer: 观察者

3. 实例

3-1. 主题抽象类
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public abstract class Observable {
    // 用一个 List 来保存该对象上所有绑定的事件监听器
    List<Observer> observers = new ArrayList<Observer>();

    // 定义一个方法, 用于从该主题上注册观察者
    public void registObserver(Observer o) {
        observers.add(o);
    }

    // 定义一个方法,用于从该主题中删除观察者
    public void removeObserver(Observer o) {
        observers.add(o);
    }

    // 通知该主题上注册的所有观察者
    public void notifyObservers(Object value) {
        // 遍历注册到该被观察者上的所有观察者
        for (Iterator<Observer> it = observers.iterator(); it.hasNext();) {
            Observer o = it.next();
            // 显示每个观察者的update方法
            o.update(this, value);
        }
    }
}

3-2. 主题类
public class Product extends Observable {
    private String name;
    private double price;
    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    // 当程序调用 name 的 setter 方法来修改 Product 的 name 属性时
    // 程序自然触发该对象上注册的所有观察者
    public void setName(String name) {
        this.name = name;
        notifyObservers(name);
    }

    public double getPrice() {
        return price;
    }

    // 当程序调用 price 的 setter 方法来修改 Product 的 price 属性时
    // 程序自然触发该对象上注册的所有观察者
    public void setPrice(double price) {
        this.price = price;
        notifyObservers(price);
    }
}

3.3 观察者接口
public interface Observer {
    void update(Observable o, Object arg);
}

3-4. 观察者 (1)
public class NameObserver implements Observer {
    // 实现观察者必须实现的 update 方法
    public void update(Observable o, Object arg) {
        if (arg instanceof String) {
            String name = String.valueOf(arg);
            System.out.println("名称观察者:" + o + "物品名称已经改变为: " + name);
        }
    }
}

3-5. 观察者 (2)
public class PriceObserver implements Observer {
    // 实现观察者必须实现的 update 方法
    public void update(Observable o, Object arg) {
        if (arg instanceof Double) {
            System.out.println("价格观察者:" + o + "物品价格已经改变为: " + arg);
        }
    }
}

3-6. 测试类
public class Test {
    public static void main(String[] args) {
        // 创建一个被观察者对象
        Product p = new Product("电视机", 176);
        // 创建两个观察者对象
        NameObserver no = new NameObserver();
        PriceObserver po = new PriceObserver();
        // 向被观察对象上注册两个观察者对象
        p.registObserver(no);
        p.registObserver(po);
        // 程序调用 setter 方法来改变 Product 的 name 和 price 属性
        p.setName("书桌");
        p.setPrice(345f);
    }
}

0 件のコメント:

コメントを投稿