• 首页

  • 归档

  • 分类

  • 标签

  • 喵星人

  • 心情

  • 关于
W e A r e F a m i l y ! m i a o ~
W e A r e F a m i l y ! m i a o ~

柴子

青春流逝,记录往昔

05月
06
后端

设计模式-观察者

发表于 2022-05-06 • 字数统计 3525 • 被 23 人看爆

当某个对象发生状态改变需要通知第三方的时候,观察者模式就特别适合胜任这样的工作。
以线程Thread为例,将任务执行的每个阶段通知给观察者

定义Observable接口

public interface Observable {

    /**
     * 任务生命周期
     */
    enum Cycle {
        STARTED, RUNNING, DONE, ERROR
    }

    /**
     * 获取当前任务生命周期状态
     *
     * @return
     */
    Cycle getCycle();

    /**
     * 定义线程启动方法,主要作用是为了屏蔽Thread的其他方法
     */
    void start();

    /**
     * 定义线程打断方法,也是为了屏蔽Thread的其他方法
     */
    void interrupt();


}

该接口主要暴露给调用者使用,四个枚举类型分别代表当前任务执行的阶段

定义TaskLifeCycle接口

public interface TaskLifeCycle<T> {

    /**
     * 任务启动时触发
     *
     * @param thread
     */
    void onStart(Thread thread);

    /**
     * 任务运行时触发
     *
     * @param thread
     */
    void onRunning(Thread thread);

    /**
     * 任务完成时触发
     *
     * @param thread
     * @param result
     */
    void onFinish(Thread thread, T result);

    /**
     * 任务报错时触发
     *
     * @param thread
     * @param ex
     */
    void onError(Thread thread,Exception ex);

}

该接口定义了任务执行的生命周期该被触发的方法

DefaultLifeCycle

public class DefaultLifeCycle<T> implements TaskLifeCycle<T> {

    @Override
    public void onStart(Thread thread) {
        System.out.println("任务启动成功");
    }

    @Override
    public void onRunning(Thread thread) {
        System.out.println("任务正在运行");
    }

    @Override
    public void onFinish(Thread thread, T result) {
        System.out.println("任务运行完成");
        if (!Objects.isNull(result)) System.out.println("运行结果为:" + result);
    }

    @Override
    public void onError(Thread thread, Exception ex) {
        System.out.println("任务运行出错:" + ex.getMessage());
    }
}

该类是为TaskLifeCycle的默认实现

Task接口定义

@FunctionalInterface
public interface Task<T> {

    /**
     * 任务执行接口,该接口允许有返回值
     *
     * @return
     */
    T call();
}

该接口类似与Runnable接口,负责任务逻辑执行单元

ObservableThread实现

import java.util.Objects;

public class ObservableThread<T> extends Thread implements Observable {

    private final TaskLifeCycle<T> lifeCycle;

    private final Task<T> task;

    private Cycle cycle;

    /**
     * 指定Task实现,默认情况下使用DefaultLifeCycle
     *
     * @param task
     */
    public ObservableThread(Task<T> task) {
        this(new DefaultLifeCycle<T>(), task);
    }

    /**
     * 指定TaskLifeCycle实现与Task实现
     *
     * @param lifeCycle
     * @param task
     */
    public ObservableThread(TaskLifeCycle<T> lifeCycle, Task<T> task) {
        if (Objects.isNull(task)) throw new IllegalArgumentException("The task is required");
        this.lifeCycle = lifeCycle;
        this.task = task;
    }

    /**
     * 修饰为final,不允许子类再次对其进行重写,导致整个生命周期监控失效
     */
    @Override
    public final void run() {
        //在执行线程逻辑单元的时候,分别触发相应的事件
        this.update(Cycle.STARTED, null, null);
        try {
            this.update(Cycle.RUNNING, null, null);
            T result = this.task.call();
            this.update(Cycle.DONE, result, null);
        } catch (Exception ex) {
            this.update(Cycle.ERROR, null, ex);
        }


    }

    /**
     * 触发事件
     *
     * @param cycle
     * @param result
     * @param ex
     */
    private void update(Cycle cycle, T result, Exception ex) {
        this.cycle = cycle;
        if (Objects.isNull(lifeCycle)) return;
        try {
            switch (cycle) {
                case STARTED: {
                    this.lifeCycle.onStart(currentThread());
                    break;
                }
                case RUNNING: {
                    this.lifeCycle.onRunning(currentThread());
                    break;
                }
                case DONE: {
                    this.lifeCycle.onFinish(currentThread(), result);
                    break;
                }
                case ERROR: {	
                    this.lifeCycle.onError(currentThread(), ex);
                    break;
                }
            }

        } catch (Exception e) {
	    //如果在响应事件时出现异常,则什么也不做,保证任务正常执行,如果是任务运行时出现了错误,则抛出
            if (cycle == Cycle.ERROR) {
                throw e;
            }
        }
    }

    @Override
    public Cycle getCycle() {
        return this.cycle;
    }

}

重写父类的run方法,触发不同阶段该触发的方法。修饰为final,不允许子类再次对其进行重写,导致整个生命周期监控失效

测试1

    public static void main(String[] args) {
        ObservableThread observableThread = new ObservableThread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 112;
        });
        observableThread.start();
    }

输出结果

任务启动成功
任务正在运行
任务运行完成
运行结果为:112

测试2

    public static void main(String[] args) {
        TaskLifeCycle taskLifeCycle = new DefaultLifeCycle() {
            @Override
            public void onFinish(Thread thread, Object result) {
                System.out.println("重写任务完成监听,运行结果为:" + result);
            }
        };
        ObservableThread observableThread = new ObservableThread(taskLifeCycle, () -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 112;
        });
        observableThread.start();
    }

输出结果

任务启动成功
任务正在运行
重写任务完成监听,运行结果为:112
分享到:
基于BIO模型手写Tomcat
定时跑批任务
  • 文章目录
  • 站点概览
柴子

内蒙 柴子

what do U want?

Github QQ Email RSS
最喜欢的电影
最喜欢的游戏
最喜欢的音乐
最喜欢的图书
最喜欢的动漫
夏洛特的烦恼
英雄联盟
痴心绝对
数据库从入门到删库跑路
斗破苍穹
看爆 Top5
  • 微信getUserProfile兼容性调整以及uniapp写法 1,866次看爆
  • gateway转发微服务请求丢失header参数 855次看爆
  • mybatis-plus代码生成器 848次看爆
  • Spring Boot Security从入门到进阶到高级 444次看爆
  • 物业报修系统设计-简化版 425次看爆
转载注明出处

站点已萌萌哒运行 00 天 00 小时 00 分 00 秒(●'◡'●)ノ♥

Copyright © 2022 柴子 京ICP备17035556号-1

由 Halo 强力驱动 · Theme by Sagiri · 站点地图