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

    设计模式 之 观察者模式

    观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

    -- 阎宏博士的《JAVA与模式》


     

    例:Button事件模型

    第一版:以最简单的方式实现Button被按下时处理自己的业务

    一个普通的Button,当被按下时将自己的pressed状态改为true
     1 public class MyButton {
     2     private boolean pressedState = false;
     3     
     4     public boolean isPressed() {
     5         return pressedState;
     6     }
     7     
     8     public void pressed() {
     9         pressedState = true;
    10     }
    11 }
    View Code
    要想在Button按下后处理自己的业务,则必须启动一个线程不断查看Button的状态
    public class Business implements Runnable {
        private MyButton btn;
        public Business(MyButton btn) {
            this.btn = btn;
        }
        
        @Override
        public void run() {
            while(!btn.isPressed()) {
                try {
                    TimeUnit.MILLISECONDS.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            process();
        }
        
        private void process() {
            System.out.println("Button pressed!");
        }
    }
    View Code
    测试
    1 public class Test {
    2     public static void main(String[] args) throws InterruptedException {
    3         MyButton btn = new MyButton();
    4         Business business = new Business(btn);
    5         new Thread(business).start();
    6         TimeUnit.SECONDS.sleep(3);
    7         btn.pressed();
    8     }
    9 }
    View Code

     OK,虽然满足了需求,但很浪费资源,因为所有等待该Button按下时处理业务的对象必须启动一个线程实时看看Button的状态。

    第二版:改进第一版,当Button被按下时通知需要做出响应的业务

    Button里增加对业务的引用,用于被按下时通知业务做出响应
    public class MyButton {
        private boolean pressedState = false;
        
        private Business business;
        
        public MyButton(Business business) {
            this.business = business;
        }
        
        public boolean isPressed() {
            return pressedState;
        }
        
        public void pressed() {
            pressedState = true;
            business.process();
        }
    }
    View Code
    此时,业务这块需提供对Button被按下时的响应
    public class Business {
        public void process() {
            System.out.println("Button pressed!");
        }
    }
    View Code
    测试
    public class Test {
        public static void main(String[] args) throws InterruptedException {
            Business business = new Business();
            MyButton btn = new MyButton(business);
            TimeUnit.SECONDS.sleep(3);
            btn.pressed();
        }
    }
    View Code

    OK,这时效率问题已经不存在了,可是现实中,Business不可能都一样,且很多情况下需要根据Button按下的时间,事件源做出不同的响应。

    第三版:抽象封装

    封装一个事件源
    public class ActionEvent {
        long when;
        Object source;
        
        public ActionEvent(long when, Object source) {
            super();
            this.when = when;
            this.source = source;
        }
        
        public long getWhen() {
            return System.currentTimeMillis();
        }
        
        public Object getSource() {
            return source;
        }
    }
    View Code
    抽象出需要对Button被按下时做出响应的业务接口
    public interface ActionListener {
        public void actionPerformed(ActionEvent e);
    }
    View Code
    需要对Button被按下做出响应的业务
    public class Business implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Button pressed! --" + e.getWhen());
        }
    }
    View Code
    重新封装Button
    public class MyButton {
        private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
        
        private boolean pressedState = false;
        
        public void addActionListeners(ActionListener l) {
            actionListeners.add(l);
        }
        
        public boolean isPressed() {
            return pressedState;
        }
        
        public void pressed() {
            pressedState = true;
            ActionEvent e = new ActionEvent(System.currentTimeMillis(), this);
            for(int i=0; i<actionListeners.size(); i++) {
                ActionListener l = actionListeners.get(i);
                l.actionPerformed(e);
            }
        }
    }
    View Code
    测试
    public class Test {
        public static void main(String[] args) throws InterruptedException {
            Business business = new Business();
            MyButton btn = new MyButton();
            btn.addActionListeners(business);
            TimeUnit.SECONDS.sleep(3);
            btn.pressed();
        }
    }
    View Code

     OK,这就是JDK中事件的处理逻辑,也是观察者模式的完美应用。

    作者:踮起脚尖眺望
    出处:http://www.cnblogs.com/wangj1130
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Linux学习笔记总结--CentOS 设置静态IP
    LAMP环境部署总结
    expect批量分发公钥
    CentOS6.5一键安装MySQL5.5.32(源码编译)
    CentOS6.5 一键部署运行环境shell脚本
    CentOS 更新yum源
    centos 6.6编译安装nginx
    安装Oracle数据库和PLSQL连接数据库
    ABAP 取字段的简短描述
    ABAP OLE常用方法和属性
  • 原文地址:https://www.cnblogs.com/wangj1130/p/4822597.html
Copyright © 2011-2022 走看看