美文网首页
第5章 -行为型模式-观察者模式

第5章 -行为型模式-观察者模式

作者: 一介书生独醉江湖 | 来源:发表于2022-07-15 10:59 被阅读0次
行为型模式(Behavioral Pattern)是对不同的对象之间划分责任和算法的抽象化;
行为型模式共有11种:
■ 模板方法模式
■ 命令模式
■ 责任链模式
■ 策略模式
■ 迭代器模式
■ 中介者模式
■ 观察者模式
■ 备忘录模式
■ 访问者模式
■ 状态模式
■ 解释器模式
一、观察者模式的简介
■ 观察者模式(Observer Pattern)也称发布订阅模式;
■ 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新;
image.png
观察者模式4个角色:
■ 抽象主题(Subject)角色:
  该角色又称为“被观察者”,可以增加和删除观察者对象;
■ 抽象观察者(Observer)角色:
  该角色为所有的具体观察者定义一个接口,在得到主题的通知时更新自己;
■ 具体主题(Concrete Subject)角色:
  该角色又称为“具体被观察者”,它将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知;
■ 具体观察者(Concrete Observer)角色:
  该角色实现抽象观察者所要求的更新接口,以便使自身的状态与主题的状态相协调;
/**
 * 抽象主题
 */
public interface Subject {

    /**
     * 登记一个新的观察者
     * @param obs
     */
    void attach(Observer obs);

    /**
     * 删除一个登记过的观察者
     * @param obs
     */
    void detach(Observer obs);

    /**
     * 通知所有登记过的观察者对象
     */
    void notifyObserver();

}
/**
 * 抽象观察者
 */
public interface Observer {

    void update();
}
import java.util.Enumeration;
import java.util.Vector;

/**
 * 具体主题
 */
public class ConcreteSubject implements Subject{

    private Vector<Observer> obsVector = new Vector<>();

    /**
     * 登记一个观察者
     * @param obs
     */
    @Override
    public void attach(Observer obs) {
        obsVector.add(obs);
    }

    /**
     * 删除一个观察者
     * @param obs
     */
    @Override
    public void detach(Observer obs) {
        obsVector.remove(obs);
    }

    /**
     * 通知所有登记过的观察者对象
     */
    @Override
    public void notifyObserver() {
        for(Observer obs : obsVector){
            obs.update();
        }
    }

    /**
     * 返回观察者集合的Enumeration对象
     * @return
     */
    public Enumeration<Observer> observers(){
        return obsVector.elements();
    }

    /**
     * 业务方法,改变状态
     */
    public void change(){
        this.notifyObserver();
    }
}
/**
 * 具体观察者
 */
public class ConcreteObserver implements Observer{
    /**
     * 实现更新方法
     */
    @Override
    public void update() {
        System.out.println("收到通知,并进行处理");
    }

}
/**
 * 应用程序
 */
public class Client {

    public static void main(String[] args){

        /**
         * 创建一个主题(被观察者)
         */
        ConcreteSubject subject = new ConcreteSubject();

        /**
         * 创建一个观察者
         */
        Observer obs = new ConcreteObserver();

        /**
         * 登记观察者(3个)
         */
        subject.attach(obs);
        subject.attach(obs);
        subject.attach(obs);

        /**
         * 删除观察者(1个)
         */
        subject.detach(obs);
        /**
         * 改变状态
         */
        subject.change();
    }
}
# 控制台输出:
收到通知,并进行处理
收到通知,并进行处理
二、观察者模式的优缺点
观察者模式的优点:
  ■ 观察者和被观察者之间是抽象耦合;
    被观察者角色所知道的只是一个具体观察者集合,被观察者并不认识任何一个具体的观察者;由于被观察者和观察者没有紧密的耦合在一起,因此它们可以属于不同的抽象化层次,且都非常容易扩展;
  ■ 支持广播通信;
    被观察者会向所有登记过的观察者发出通知,这就是一个触发机制,形成一个触发链;
观察者模式的缺点:
  ■ 如果一个主题有多个直接或间接的观察者,则通知所有的观察者会花费很多时间,且开发和调试都比较复杂;
  ■ 如果在主题之间有循环依赖,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式时要特别注意这一点;
  ■ 如果对观察者的通知是通过另外的线程进行异步投递,系统必须保证投递的顺序执行;
  ■ 虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有提供相应的机制使观察者知道所观察的对象是如何发生变化;
观察者模式的应用场景:
  ■ 关联行为场景;
  ■ 事件多级触发场景;
  ■ 跨系统的消息交换场景,如消息队列的处理机制;
三、观察者模式的实例
# 使用观察者模式模拟按钮控件的事件处理机制;
image.png
/**
 * 该接口对可单击控件的功能方法进行抽象
 */
public interface Clickable {

    /**
     * 单击
     */
    void click();

    /**
     * 添加单击事件的观察者
     * @param observer
     */
    void addClickableObserver(ClickableObserver observer);

    /**
     * 删除单击事件的观察者
     * @param observer
     */
    void removeClickableObserver(ClickableObserver observer);
}
/**
 * 该接口表示可单击控件的单击事件观察者
 */
public interface ClickableObserver {

    /**
     * 发生单击事件时的操作
     * @param clickable
     */
    void clicked(Clickable clickable);
}
import java.util.ArrayList;
import java.util.List;

/**
 * 按钮控件
 */
public class Button implements Clickable{
    /**
     * 存储注册过的单击事件观察者
     */
    List<ClickableObserver> observerList = new ArrayList<>();

    /**
     * 颜色
     */
    String color;

    /**
     * 坐标
     */
    int x,y;

    @Override
    public void click() {
        System.out.println("按钮被单击");

        /**
         * 执行所有观察者事件的处理方法
         */
        for(int i = observerList.size() - 1; i >= 0 ;i--){
            observerList.get(i).clicked(this);
        }
    }

    @Override
    public void addClickableObserver(ClickableObserver observer) {
        observerList.add(observer);
    }

    @Override
    public void removeClickableObserver(ClickableObserver observer) {
        observerList.remove(observer);
    }

    @Override
    public String toString() {
        return "Button{" +
                "color='" + color + '\'' +
                ", x=" + x +
                ", y=" + y +
                '}';
    }
}
/**
 * 修改按钮颜色的观察者
 */
public class ChangeColorObserver implements ClickableObserver{

    @Override
    public void clicked(Clickable clickable) {
        Button button = (Button) clickable;
        button.color = "红色";
    }
}
/**
 * 修改按钮坐标的观察者
 */
public class ChangeCoordinateObserver implements ClickableObserver{

    @Override
    public void clicked(Clickable clickable) {
        Button button = (Button) clickable;
        button.x = 100;
        button.y = 90;
    }
}
/**
 * 其他某种业务的观察者
 */
public class OtherObserver implements ClickableObserver{

    @Override
    public void clicked(Clickable clickable) {
        System.out.println("执行其他操作");
    }
}
/**
 * 测试类
 */
public class Test {

    public static void main(String[] args){
        Button button = new Button();
        button.color = "白色";
        button.x = 0 ;
        button.y = 0 ;

        button.addClickableObserver(new ChangeColorObserver());
        button.addClickableObserver(new ChangeCoordinateObserver());
        button.addClickableObserver(new OtherObserver());

        button.click();
        System.out.println(button);
    }
}
# 控制台输出:
按钮被单击
执行其他操作
Button{color='红色', x=100, y=90}
参考:
摘录 《设计模式(Java版)》韩敬海主编;(微信读书APP中有资源,可以直接阅读)

相关文章

网友评论

      本文标题:第5章 -行为型模式-观察者模式

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