设计模式之观察者模式(Java实现)

简介: 设计模式之观察者模式(Java实现)

一、认识观察者模式


观察者模式定义:属于对象行为模式,当多个对象之间存在一对多的依赖关系,即一个对象的状态发生改变时,所以依赖它的对象都会得到通知并被自动更新。这种模式有时又被称为发布-订阅模式、模型-视图模式。


结构:


抽象主题角色(Subject):即抽象类,提供了添加、移除观察者的方法,以及一个通知所有观察者的抽象方法。

具体主题角色(Concrete Subject):也称为具体目标类,实现抽象目标中的通知方法,一旦该类内部发生了什么改变时,通知所有注册过的观察者对象。

抽象观察者(Observer):是一个抽象类或接口,包含了一个更新自己的抽象方法,当接到具体主题的更改时被调用。

具体观察者(Concrete Observer):实现抽象观察者中的更新方法,一旦目标角色发出更新通知时会调用该更新方法来更新自身的状态。



优缺点:


优点:降低了目标与观察者之间的耦合关系,符合依赖倒置原则,开闭原则。目标与观察者之间建立了一套触发机制。

缺点:目标与观察者之间依赖关系并没有完全解除,可能出现循环引用。并且若是当在主题角色中的观察者过多时,通知发布会花费很多时间,影响程序的效率。

实际应用场景:


JDK中的java.util.Observable。

Spring中的org.springframework.context.ApplicationListener。


二、实现观察者模式


实现过程

demo见xyz.changlu.observer包下代码:



抽象观察者(接口):Observer


public interface Observer {
    void response();
}


抽象主题类:Subject


public abstract class Subject {
    protected List<Observer> observers = new ArrayList<>();
    //添加观察者到集合中
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    //移除指定观察者
    public void removeObserver(Observer observer){
        observers.remove(observer);
    }
    //具体通知方法让实现类去实现
    public abstract void notifyAllObserver();
}



具体观察者:Task1、Task2


//具体观察者1号
public class Task1 implements Observer {
    @Override
    public void response() {
        System.out.println("Task1收到通知,正在执行任务2.....");
    }
}
//具体观察者2号
public class Task2 implements Observer {
    @Override
    public void response() {
        System.out.println("Task2收到通知,正在执行任务2.....");
    }
}


具体主题者:ConcreteSubject


public class ConcreteSubject extends Subject {
    @Override
    public void notifyAllObserver() {
        System.out.println("收到通知");
        //开始通知到所有的观察者
        for (Observer observer : observers) {
            observer.response();
        }
    }
}


测试程序:测试类Customer


public class Customer {
    public static void main(String[] args) {
        //创建两个任务
        Task1 task1 = new Task1();
        Task2 task2 = new Task2();
        //创建主题角色,并添加两个观察者(及任务)
        ConcreteSubject subject = new ConcreteSubject();
        subject.addObserver(task1);
        subject.addObserver(task2);
        //进行更新通知
        subject.notifyAllObserver();
    }
}



首先将多个任务(即观察者)添加到主题类中(存放在一个list集合里),一旦ConcreteSubject主题类进行了更新操作,即可调用其实现Subject抽象类的实现方法notifyAllObserver()来通知观察者集合中的各个观察者执行任务。

说明:解决的是当一个对象进行更新或其他操作时对应要去更改执行或通知多个任务时,我们即可以使用观察者模式。



实际应用情况描述

问题描述


若是主题进行了更新,并且该更新涉及到了需要个部分,此时你会怎么呢?若是没有了解过观察者模式的也许会这样:


class Weather{
    //执行更新操作
    public void update(){
        dao.update();//本方法核心的更新操作
        //通知的操作
        Task task = new Task();
        Task2 task2 = new Task2();
        task.doThing1();
        task2.doThing2();
    }
}
class Task{
    void doThing1(){
        ...
    }
}
class Task2{
    void doThing2(){
        ....
    }
}



你可能会在update()操作中去new多个对象并且逐一执行,若是某一天要少通知一个单位的话还需要去手动删除…



解决对策


创建一个抽象类,其包含了一个集合专门用来存放多个观察者对象,并包含添加、移除操作:


//抽象主题
public abstract class Subject {
    protected List<Observer> observers = new ArrayList<>();
    //添加观察者到集合中
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    //移除指定观察者
    public void removeObserver(Observer observer){
        observers.remove(observer);
    }
    public abstract void notifyAllObserver();
}



再创建一个抽象观察者接口,其带有一个通知方法:


public interface Observer {
    void response();
}


万事具备了,我们开始改造原来的两个类:


class Weather extends Subject{
    //执行更新操作
    public void update(){
        dao.update();//本方法核心的更新操作
        //调用通知操作即可!!!
        notifyAllObserver();
    }
    //实现一个通知方法
    @Override
    public void notifyAllObserver() {
        //通知所有的观察者开始执行其自己的操作
        for (Observer observer : observers) {
            observer.response();
        }
    }
}
//两个任务分别实现了观察者接口
class Task implements Observer{
    void doThing1(){
        ...
    }
    @Override
    public void response() {
        doThing1();//不仅仅可以添加该方法,还可以添加其他方法
    }
}
class Task2{
    void doThing2(){
        ....
    }
    @Override
    public void response() {
        doThing2();//不仅仅可以添加该方法,还可以添加其他方法
    }
}


测试使用时:


public class Customer {
    public static void main(String[] args) {
        Weather weather = new Weather();
        //添加指定的任务
        weather.addObserver(new Task());
        weather.addObserver(new Task2());
        //执行其中的更新操作
        weather.update();//此时调用更新操作时,自动会执行集合中的所有观察者操作
    }
}


感悟:在对观察者模式进行思考时,将模式应用到实际案例中去,去通过使用设计模式来去解决整个项目的架构问题,提高方法解耦!!!



总结


1、对于观察者模式,在出现一对多的关系操作时可以进行使用来实现方法解耦,一般应当是当要执行更新或其他操作影响到很多个对象时,为了方便管理通知可以使用到该模式。


2、优点是符合开闭原则、依赖倒置原则,对于目标与观察者之间建立了连接。缺点是依赖关系没有完全解除,若是观察者过多通知发布会耗费很多时间,影响程序的效率。

相关文章
|
1月前
|
设计模式 监控 Java
Kotlin - 改良设计模式 - 观察者模式
Kotlin - 改良设计模式 - 观察者模式
51 3
|
1月前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
|
20天前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
22天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
36 1
|
1月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
36 4
|
1月前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
28 3
|
2月前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
35 2
|
1月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
Java
JAVA内置的观察者模式样本
DisplayElement.java public interface DisplayElement { public void display(); } CurrentConditionsDisplay.
687 0
|
6天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
36 6
下一篇
DataWorks