行为型模式:20-观察者模式

2021-06-20  本文已影响0人  综合楼

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,
使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器
(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

image.png

在观察者模式结构图中包含如下几个角色:

● Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集
合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察
者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。

● ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数
据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义
的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。

● Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接
口声明了更新数据的方法update(),因此又称为抽象观察者。

● ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它
存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观
察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自
己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。

代码示例:

import java.util.ArrayList;

public abstract class MySubject {
    protected ArrayList observers = new ArrayList();

    //注册方法
    public void attach(MyObserver observer) {
        observers.add(observer);
    }

    //注销方法
    public void detach(MyObserver observer) {
        observers.remove(observer);
    }

    public abstract void cry(); //抽象通知方法
}
public interface MyObserver {
    void response();  //抽象响应方法
}
------------------------------------------------------
public class Cat extends MySubject {
    public void cry() {
        System.out.println("猫叫!");
        System.out.println("----------------------------");

        for (Object obs : observers) {
            ((MyObserver) obs).response();
        }

    }
}
------------------------------------------------------
public class Dog implements MyObserver {
    public void response() {
        System.out.println("狗跟着叫!");
    }
}
------------------------------------------------------
public class Mouse implements MyObserver {
    public void response() {
        System.out.println("老鼠努力逃跑!");
    }
}
------------------------------------------------------
public class Pig implements MyObserver {
    public void response() {
        System.out.println("猪没有反应!");
    }
}
public class Client {
    public static void main(String a[]) {
        MySubject subject = new Cat();

        MyObserver obs1, obs2, obs3;
        obs1 = new Mouse()  ;
        obs2 = new Mouse();
        obs3 = new Dog();

        subject.attach(obs1);
        subject.attach(obs2);
        subject.attach(obs3);

        MyObserver obs4;
        obs4 = new Pig();
        subject.attach(obs4);

        subject.cry();
    }
}
image.png

JDK对观察者模式的支持

image.png

自定义登录组件

image.png
import java.util.EventObject;

public class LoginEvent extends EventObject {
    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 this.password;
    }
}
//Concrete Subject
public class LoginBean extends JPanel implements ActionListener {
    private JLabel labUserName, labPassword;
    private JTextField txtUserName;
    private JPasswordField txtPassword;
    private JButton btnLogin, btnClear;

    private LoginEventListener lel;  //Abstract Observer

    private 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);//As a concrete observer for another subject,ActionListener as the abstract observer.
    }

    //Add an observer.
    public void addLoginEventListener(LoginEventListener lel) {
        this.lel = lel;
    }

    //private or protected as the notify method
    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("");
        }
    }
}
//Abstract Observer
public interface LoginEventListener extends EventListener {
    public void validateLogin(LoginEvent event);
}
------------------------------------------------------------------------------------------------------
//Concrete Observer
public class LoginValidatorA extends JFrame implements LoginEventListener {
    private JPanel p;
    private LoginBean lb;
    private JLabel lblLogo;

    public LoginValidatorA() {
        super("Bank of China");
        p = new JPanel();
        this.getContentPane().add(p);
        lb = new LoginBean();
        lb.addLoginEventListener(this);

        Font f = new Font("Times New Roman", Font.BOLD, 30);
        lblLogo = new JLabel("Bank of China");
        lblLogo.setFont(f);
        lblLogo.setForeground(Color.red);

        p.setLayout(new GridLayout(2, 1));
        p.add(lblLogo);
        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);
    }
}
------------------------------------------------------------------------------------------------------
public class LoginValidatorB extends JFrame implements LoginEventListener {
    private JPanel p;
    private LoginBean lb;
    private JLabel lblLogo;

    public LoginValidatorB() {
        super("China Mobile");
        p = new JPanel();
        this.getContentPane().add(p);
        lb = new LoginBean();
        lb.addLoginEventListener(this);

        Font f = new Font("Times New Roman", Font.BOLD, 30);
        lblLogo = new JLabel("China Mobile");
        lblLogo.setFont(f);
        lblLogo.setForeground(Color.blue);

        p.setLayout(new GridLayout(2, 1));
        p.add(lblLogo);
        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("Rigth details!"), "alert", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    public static void main(String args[]) {
        new LoginValidatorB().setVisible(true);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读