java实现观察者模式

作者: Pursuer96 | 来源:发表于2017-12-12 15:41 被阅读20次
    123.jpg123.jpg

    Basic Framework

    屏幕快照 2017-12-12 15.35.16.png屏幕快照 2017-12-12 15.35.16.png
    • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
    • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
    • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
    • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
    屏幕快照 2017-12-12 15.26.33.png屏幕快照 2017-12-12 15.26.33.png

    LoginEvent.java

    package Observer_Pattern;
    
    import java.util.EventObject;
    
    public class LoginEvent extends EventObject {
        //LonginEvent表示事件类,它用于封装与事件有关的信息。它不是观察者模式的一部分,但它可以在目标对象和观察者对象之间传递数据
        private String userName;
        private String passWord;
    
        public LoginEvent( Object source, String userName, String passWord ) {
            super( source );
            this.userName = userName;
            this.passWord = passWord;
        }
    
        public void setUserName( String userName ) {
            this.userName = userName;
        }
    
        public String getUserName( ) {
            return this.userName;
        }
    
        public void setPassWord( String passWord ) {
            this.passWord = passWord;
        }
    
        public String getPassWord( ) {
            return passWord;
        }
    
    }
    

    LoginEventListener.java

    package Observer_Pattern;
    
    import java.util.EventListener;
    
    public interface LoginEventListener extends EventListener {
        //抽象观察者(登录事件监听器)
        public void validateLogin( LoginEvent event );//声明响应方法
    
    }
    

    LoginBean.java

    package Observer_Pattern;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class LoginBean extends JPanel implements ActionListener {
        //LoginBean充当具体目标类(登录控件)
    
        JLabel labUserName;
        JLabel labPassWord;
        JTextField txtUserName;
        JPasswordField txtPassWord;
        JButton btnLogin;
        JButton btnClear;
    
        LoginEventListener lel;//定义一个抽象观察者对象
        LoginEvent le;//定义一个事件对象,用于传输数据
    
        public LoginBean() {
    
            this.setLayout( new GridLayout(3,2) );
            labUserName = new JLabel( "User Name:" );
            add( labUserName );
    
            txtUserName = new JTextField( 20 );
            add( txtUserName );
    
            labPassWord = new JLabel( "PassWord:" );
            add( labPassWord );
    
            txtPassWord = new JPasswordField( 20 );
            add( txtPassWord );
    
            btnLogin = new JButton( "Login" );
            add( btnLogin );
    
            btnClear = new JButton( "Clear" );
            add( btnClear );
    
            btnClear.addActionListener( this );
            btnLogin.addActionListener( this );
    
        }
    
        //实现注册方法
        void addLoginEventListener( LoginEventListener lel ) {
            this.lel = lel;
        }
    
        //实现通知方法
        private void fireLoginEvent( Object object, String userName, String PassWord ) {
            le = new LoginEvent( btnLogin, userName, PassWord );
            lel.validateLogin( le );
        }
    
        public void actionPerformed( ActionEvent event ) {
            if( btnLogin == event.getSource() ){
                String userName = this.txtUserName.getText();
                String PassWord = this.txtPassWord.getText();
    
                fireLoginEvent( btnLogin, userName, PassWord );
            }
            if( btnClear == event.getSource() ){
                this.txtUserName.setText( "" );
                this.txtPassWord.setText( "" ); 
            }
        }
    
    }
    

    LoginValidatorA.java

    package Observer_Pattern;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.GridLayout;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    
    public class LoginValidatorA extends JFrame implements LoginEventListener {
    
        //具体观察者类
        //判断用户名和密码是否为空
        private JPanel p;
        private LoginBean lb;//定义具体目标
        private JLabel lbLogo;
        public LoginValidatorA() {
            super( "GitHub" );
            p = new JPanel();
            this.getContentPane().add( p );
            lb = new LoginBean();
            lb.addLoginEventListener( this );//调用目标对象的注册方法
    
            Font f = new Font( "Times New Roman", Font.BOLD, 30 );
            lbLogo = new JLabel( "GitHub" );
            lbLogo.setForeground( Color.blue );
    
            p.setLayout( new GridLayout( 2,1 ) );
            p.add( lbLogo );
            p.add( lb );
            p.setBackground( Color.pink );
            this.setSize( 600,200 );
            this.setVisible( true );
        }
    
        //实现在抽象观察者中声明的相应方法
        public void validateLogin( LoginEvent event ){
            String userName = event.getUserName();
            String passWord = event.getPassWord();
    
            if( 0 == userName.trim().length() || 0 == passWord.trim().length() ){
                JOptionPane.showMessageDialog( this, new String(" UserName or PassWord is empty! "), "alert", JOptionPane.ERROR_MESSAGE );
            }
            else{
                JOptionPane.showMessageDialog( this, new String(" Valid Login Info! "),"alert",JOptionPane.INFORMATION_MESSAGE );
            }
        }
    
        public static void main( String args[] ){
            new LoginValidatorA().setVisible( true );
        }
    }
    

    LoginValidatorB.java

    package Observer_Pattern;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.GridLayout;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    
    public class LoginValidatorB extends JFrame implements LoginEventListener {
    
        //具体观察者类
        //判断用户名和密码是否相同
        private JPanel p;
        private LoginBean lb;//定义具体目标
        private JLabel lbLogo;
        public LoginValidatorB() {
            super( "FaceBook" );
            p = new JPanel();
            this.getContentPane().add( p );
            lb = new LoginBean();
            lb.addLoginEventListener( this );//调用目标对象的注册方法
    
            Font f = new Font( "Times New Roman", Font.BOLD, 30 );
            lbLogo = new JLabel( "FaceBook" );
            lbLogo.setForeground( Color.red );
    
            p.setLayout( new GridLayout( 2,1 ) );
            p.add( lbLogo );
            p.add( lb );
            p.setBackground( new Color(163, 185, 255) );
            this.setSize( 600,200 );
            this.setVisible( true );
        }
    
        //实现在抽象观察者中声明的相应方法
        public void validateLogin( LoginEvent event ){
            String userName = event.getUserName();
            String passWord = event.getPassWord();
    
            if( userName.equals( passWord ) ){
                JOptionPane.showMessageDialog( this, new String(" UserName must be different from passWord! "), "alert", JOptionPane.ERROR_MESSAGE );
            }
            else{
                JOptionPane.showMessageDialog( this, new String(" Right Details! "),"alert",JOptionPane.INFORMATION_MESSAGE );
            }
        }
    
        public static void main( String args[] ){
            new LoginValidatorB().setVisible( true );
        }
    }
    

    Running Effect

    屏幕快照 2017-12-12 15.24.44.png屏幕快照 2017-12-12 15.24.44.png
    屏幕快照 2017-12-12 15.26.05.png屏幕快照 2017-12-12 15.26.05.png

    Source Download

    Please click the address->Observer Pattern

    Summarize

    Usage Scenario

    1. 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
    2. 事件多级触发场景。
    3. 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

    Advantage

    • 除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。

    Disadvantage

    • 在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

    原文地址:www.iooy.com

    相关文章

      网友评论

        本文标题:java实现观察者模式

        本文链接:https://www.haomeiwen.com/subject/fkrnixtx.html