Java设计模式之观察者模式

Java设计模式之观察者模式

缘起

  • 公司内部要做个培训功能,培训有考试,考试就要有试卷
  • 在试卷完成答卷后,要计算试卷的得分,按照比例换算为培训的得分。
  • 试卷不认识培训,试卷作答结果结束的时候,需要 通知 关注试卷结果的关注者们。
  • 后期其他业务也需要用到试卷模块,所以,试卷不应该和任何的业务耦合,但要保证其他业务在关联试卷的时候,试卷的作答结果也可以通知到这个关注者。

开局

-回调函数,Java设计的时候就不支持函数,所以Java中想要函数的时候,一般用匿名内部类完成。此处,用接口来解决 要先有个 通知接口 来解耦,试卷模块只需要关联这个口,至于这个接口中做什么XXOO的事情,试卷不管。

/**
 * Summary : 通知接口
 *
 * @Author Ray
 * @Create 2020-08-13 9:50
 */
public interface Notifier<T> {
    /**
     * 通知
     *
     * @param t 通知内容
     */
    void notifier(T t);
}

  • 事件源
    试卷与通知接口进行关联
    此处的 notifiers 可以理解为广播容器。
    当考试结果提交的时候,可以通过遍历关注者的集合,将结果推送给关注者们。
package com.sogdata.ideology.biz.service.exam;

import com.sogdata.ideology.biz.entity.exam.OnlineExamInstanceResult;
import com.sogdata.ideology.notifier.Notifier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

/**
 * Summary : 试卷实例的考试结果服务
 *
 * @Author Ray
 * @Create 2020-08-04 23:09
 */
@Service
public class OnlineExamInstanceResultService {
    /**
     * 关注者集合
     */
    public static ArrayList<Notifier<OnlineExamInstanceResult>> notifiers = new ArrayList<>();
    /**
     * 通知followers
     *
     * @param onlineExamInstanceResult 试卷实例的考试结果
     */
    private void notifierAll(OnlineExamInstanceResult onlineExamInstanceResult) {
        for (Notifier<OnlineExamInstanceResult> notifier : notifiers) {
            notifier.notifier(onlineExamInstanceResult);
        }
    }

}


-观察者(关注者/跟随者)
将自己的回调函数注册到广播容器中,A/B/C三种写法都行,A/B是Java8的写法,C是8之前的写法,可以拍大腿盲测下Java8的函数是咋实现的。

package com.sogdata.ideology.biz.service.training;

import com.sogdata.ideology.biz.entity.exam.OnlineExamInstanceResult;
import com.sogdata.ideology.biz.service.exam.OnlineExamInstanceResultService;
import com.sogdata.ideology.notifier.Notifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;

/**
 * Summary : 培训参与人
 *
 * @Author Ray
 * @Create 2020-08-11 18:09
 */
@Slf4j
@Service
public class OnlineTrainingParticipantService {

    @PostConstruct
    public void followExamInstanceResult() {
    	//A 写法
        OnlineExamInstanceResultService.notifiers.add(this::updateExamInstanceResultIfExist);
        //B 写法
        OnlineExamInstanceResultService.notifiers.add(onlineExamInstanceResult -> {

        });
        //C 写法
        OnlineExamInstanceResultService.notifiers.add(new Notifier<OnlineExamInstanceResult>() {
            @Override
            public void notifier(OnlineExamInstanceResult onlineExamInstanceResult) {

            }
        });
    }

    /**
     * 将考试结果 异步写入 到的 对应的培训参与人
     *
     * @param onlineExamInstanceResult 培训结果实体
     */
    @Async
    void updateExamInstanceResultIfExist(@NotNull OnlineExamInstanceResult onlineExamInstanceResult) {

    }

   }

结尾

回忆一波,当时学这个模式的时候,Frank(我编程道路上的导师)说了一遍,我觉得我理解了,直到两年后,我才回过味来,为什么要用个notifier的接口,以及用这个的好处。设计模式很有意思,但要考虑是否有必要用,(就写个脚本,套个狗屁的设计模式,怎么快怎么来)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值