zoukankan      html  css  js  c++  java
  • 观察者模式

    定义

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

    使用场景

    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的问题,还对接口柯西化处理,运用链式编程风格,使用方便。
  • 相关阅读:
    php redis操作
    textarea 文本框根据输入内容自适应高度
    ThinkPHP5 微信接口对接公共类
    ThinkPHP5 excel 导入/导出
    NGUI 学习使用
    Unity3d 背景、音效 播放 简单demo
    Unity3D教程:制作与载入AssetBundle
    BuildPipeline.BuildAssetBundle 编译资源包
    C# 如何将对象写入文件
    unity3d IO操作
  • 原文地址:https://www.cnblogs.com/fzsyw/p/11326108.html
Copyright © 2011-2022 走看看