观察者模式

定义

定义对象间的一对多的关系,使得每当一个对象的状态改变,则所有依赖与它的对象都会得到通知并被自动更新

使用场景

  1. 观察者和被观察者是抽象耦合,利于扩展
  2. 一个对象的改变将会导致一个或多个对象的改变,不清楚具体有多少对象以及这些被影响的对象是谁的情况
  3. 如果有这样一个影响链的情况下也可以使用,例如A的改变会影响B,B的改变会影响C......,可以使用观察者模式设计一个链式触发机制。

实现方式

被观察者,商品类

import java.math.BigDecimal;
import java.util.Observable;

public class Product extends Observable {

    protected String name;
    protected BigDecimal price;
    
    public Product(String name, BigDecimal price) {
		super();
		this.name = name;
		this.price = price;
	}
   
	public String getName() {
		return name;
	}

	public BigDecimal getPrice() {
		return price;
	}

	/**
     * 商品名称变更
     * @param name 商品名称
     */
    public void setName(String name){
        this.name = name;
        setChanged();
        //通知观察者
        notifyObservers(name);
    }

    /**
     * 价格变更
     * @param price 商品价格
     */
    public void setPrice(BigDecimal price){
        this.price = price;
        setChanged();
        //通知观察者
        notifyObservers(price);
    }
}

观察者类,名称观察者

import java.util.Observable;
import java.util.Observer;

public class NameObserver implements Observer {
	
    /**
     * 更新
     */
    @Override
    public void update(Observable observable, Object arg) {
        if(arg instanceof String){
            String name = (String) arg;
            System.out.println("您关注的商品名称发生了变化,最新的商品名称是"+name);
        }
    }
}

观察者类,价格观察者

import java.math.BigDecimal;
import java.util.Observable;
import java.util.Observer;

public class PriceObserver implements Observer{

    /**
     * 更新
     * @param obj 更新对象
     */
    @Override
    public void update(Observable observable, Object arg) {
        if(arg instanceof BigDecimal){
            BigDecimal price = (BigDecimal)arg;
            System.out.println("您关注的商品价格发生了变化,最新的商品价格是:"+price);
        }
    }
}

客户端调用

import java.math.BigDecimal;

public class Test {

    public static void main(String[] args) {

        Product product = new Product("iphone 6",new BigDecimal(8999));
        System.out.println("您关注的商品的名称是:"+product.getName()+",价格是:"+product.getPrice());
        //创建观察者
        NameObserver nameObserver = new NameObserver();
        PriceObserver priceObserver = new PriceObserver();
        //加入观察者
        product.addObserver(nameObserver);
        product.addObserver(priceObserver);
        //产生变化,通知观察者
        product.setName("iphone 7");
        product.setPrice(new BigDecimal(12999));
    }
}  

扩展与思考

  1. 观察者模式与之前学习的Javascript回调函数类似,JQuery中有jQuery.Callbacks(flags),都有一套触发机制
  2. JDK中提供了java.util.Observable实现类和java.util.Observer的接口,所以实际中我们可以直接使用,而不用自己去写重复代码和建立对应的接口。
  3. 异步处理问题,一般观察者的模式默认是顺序执行的,一旦中间观察者卡壳,会影响整体的执行效率,需要考虑异步。
  4. 广播链问题,比如数据库的触发器,表A的触发器,修改表B字段,表B的触发器触发修改表C...也就是一个观察者可以有双重身份,即是观察者也是被观察者。
  5. 观察者模式可以考虑使用RxJava框架,来解决3和4的问题,还对接口柯西化处理,运用链式编程风格,使用方便。
原文地址:https://www.cnblogs.com/fzsyw/p/11326108.html