• 设计模式之观察者模式


    观察者设计模式

      定义了对象之间一对多的关系。当一个对象的状态发生变化,它所有的依赖者会收到更新通知,并作出相应的变化。

    相关对象

      主题(Subject):主题是一个接口,接口规定了具体主题需要实现的方法,如添加、删除观察者以及通知观察者更新数据的方法;

      观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更细数据的方法;

      具体主题(ConcreteSubject):是实现主题接口的一个实例;

      具体观察者(ConcreteObserver):是实现观察者接口的一个实例;

      

    使用场景

      (1)聊天室程序:一个人发送一条消息给服务器,服务器会将该消息广播给聊天室内的其他人;

      (2)邮件订阅:多人订阅了《NBA》这个相关消息,当有新消息出现的时候,通过广播给所有订阅的人;

      (3)Servlet中,监听器的实现

    测试实例

      (1)观察者

    /**
     * Observer 抽象的观察者
     * @author yangkj
     */
    public interface Observer {
    
        void update(Subject subject);
    }

      (2)主题

    /**
     * 
     * <p>
     * Subject 主题
     * <p>
     * 
     * @author <a href="mailto:yangkj@corp.21cn.com">yangkj</a>
     * @version
     * @since 2016年9月26日
     */
    public abstract class Subject {
        /**
         * 观察者列表
         */
        private List<Observer> list = new ArrayList<>();
    
        /**
         * 添加观察者
         */
        public void registerOberver(Observer obs) {
            list.add(obs);
        }
    
        /**
         * 删除观察者
         */
        public void removerOberver(Observer obs) {
            list.remove(obs);
        }
    
        /**
         * 通知所有的观察者更新
         */
        public void noticeAllObserver() {
            for (Observer obs : list) {
                obs.update(this);
            }
        }
    }

      (3)具体主题

    /**
     * ConcreteSubject 具体的主题
     * @author yangkj*/
    public class ConcreteSubject extends Subject {
        
        private int status;
    
        public int getStatus() {
            return status;
        }
    
        public void setStatus(int status) {
            this.status = status;
            //主题对象值发生变化,通知所有观察者,进行状态值变化
            this.noticeAllObserver();
        }
    }

      (4)具体观察者

    /**
     * ConcreteObserver 具体的观察者
     * @author yangkj*/
    public class ConcreteObserver implements Observer {
    
        private int status;
    
        @Override
        public void update(Subject subject) {
    
            status = ((ConcreteSubject) subject).getStatus();
    
            System.out.println("广播通知,状态值发生变化为:" + status);
        }
    
        public int getStatus() {
            return status;
        }
        public void setStatus(int status) {
            this.status = status;
        }
    }

      (5)测试代码

    public class Client {
    
        public static void main(String[] args) {
            // 新建两个观察者
            Observer obsA = new ConcreteObserver();
            Observer obsB = new ConcreteObserver();
            // 定义目标对象
            ConcreteSubject sub = new ConcreteSubject();
            sub.registerOberver(obsA);
            sub.registerOberver(obsB);
            sub.setStatus(0);
            /**
             * 添加一个观察者
             */
            Observer obsC = new ConcreteObserver();
            sub.registerOberver(obsC);
            sub.setStatus(1);
            /**
             * 移除一个观察者
             */
            sub.removerOberver(obsB);
            sub.setStatus(10);
        }
    }

      测试结果


      

      当然我们自己实现的是有缺陷的,比如没有考虑并发同步的问题;在Java.util中已经为我们提供了相关的工具类,下面我们用这些工具类完成一个观察者设计模式。

    利用java.util.Observable和java.util.Observer实现观察者模式

      (1)观察者

    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * ConcreteObserver 观察者
     * 
     * @author yangkj
     */
    public class ConcreteObserver implements Observer {
    
        private int status;
    
        @Override
        public void update(Observable o, Object arg) {
            status = ((ConcreteSubject) o).getStatus();
            System.out.println("广播通知,状态值变化为:" + status);
        }
    
        public int getStatus() {
            return status;
        }
    
        public void setStatus(int status) {
            this.status = status;
        }
    }

      (2)主题

    import java.util.Observable;
    /**
     * ConcreteObserver 具体的主题
     * 
     * @author yangkj
     */
    public class ConcreteSubject extends Observable{
    
        private int status;
    
        public int getStatus() {
            return status;
        }
        public void setStatus(int status) {
            this.status = status;
            //表示目标状态已经做了修改
            setChanged();
            //通知所有的观察者,并且将具体的状态值进行传递
            notifyObservers(status);
        }
    }

      (3)测试代码

    public class Client {
    
        public static void main(String[] args) {
            Observer obs1 = new ConcreteObserver();
            Observer obs2 = new ConcreteObserver();
            Observer obs3 = new ConcreteObserver();
            
            ConcreteSubject sub = new ConcreteSubject();
            sub.addObserver(obs1);
            sub.addObserver(obs2);
            sub.addObserver(obs3);
            sub.setStatus(20);
            
            System.out.println("广播者个数:"+sub.countObservers());
            
            sub.deleteObserver(obs3);
            System.out.println("广播者个数:"+sub.countObservers());
        }
    }

      测试结果

      

  • 相关阅读:
    计算1的个数
    【环境配置】配置git
    Spoj 9887 Binomial coefficients 构造
    程序猿与HR博弈之:有城府的表达你的兴趣爱好
    C和指针 (pointers on C)——第六章:指针(上)
    关于undo表空间配置错误的ORA-30012
    每天进步一点点——Linux系统中的异常堆栈跟踪简单实现
    javaScript 对象的使用
    手机游戏加密那点事儿_2d资源加密_1
    支持向量机
  • 原文地址:https://www.cnblogs.com/parryyang/p/5909503.html
Copyright © 2020-2023  润新知