V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huifer
V2EX  ›  Java

Java 字段监控执行事件

  •  1
     
  •   huifer · 2020-09-23 13:18:22 +08:00 · 1694 次点击
    这是一个创建于 1301 天前的主题,其中的信息可能已经有所发展或是发生改变。

    字段监控设计

    • 需求描述: 一个实体的字段可能会有后续的行为.

    • 字段有什么变化会有什么样的操作

      1. 字段变动.
        1. 常见新老数据变更的日志记录
      2. 字段直接会产生行为
        1. 发消息的场景.填写了用户 id 就发送消息
    • 上述为目前想到的字段监控可能存在的场景. 针对这样的场景做出如下设计.

    • 接口抽象

    public interface MonitoringInterface<T> {
    
    	void monitor(T t);
    
    }
    
    /**
     * 监控:字段变更.
     * 字段变更后需要做的事情
     */
    public interface MonitoringFieldChange<T> {
    
    	void filedChange(T t);
    
    }
    
    /**
     * 监控,通过字段决定后续工作.
     * 例如传递这个值会后续执行什么事情.
     */
    public interface MonitoringFieldWork<T> {
    
    	void fieldWork(T t);
    }
    
    
    • 三个接口的作用

      1. MonitoringInterface 整体监控
      2. MonitoringFieldChange 字段变更的监控
      3. MonitoringFieldWork 字段决定行为的监控
    • 综合前面的需求描述做出一个通用定义.

      • 传入对象, 通过这个对象去调用 字段变更监控方法字段决定行为的监控方法
    
    public class SupperMonitor<T> {
    
    	private final T data;
    
    	private MonitoringFieldChange<T> fieldChange;
    
    	private MonitoringFieldWork<T> fieldWork;
    
    	public SupperMonitor(T data, MonitoringFieldChange<T> fieldChange, MonitoringFieldWork<T> fieldWork) {
    		this.data = data;
    		this.fieldChange = fieldChange;
    		this.fieldWork = fieldWork;
    	}
    
    	public void monitor() {
    		this.fieldChange.filedChange(data);
    		this.fieldWork.fieldWork(data);
    	}
    
    }
    
    
    • 在这里还可以用工程去创建内部变量fieldChangefieldWork
    • 暂且称SupperMonitor是一个统筹调用对象.接下来是几个接口的实现 在实现之前定义出如下两个接口. 用来做类型限定. 下面两个接口内部填写的抽象方法是我们需要比较的字段或者需要根据某个字段去做操作的抽象 将不同的字段处理方案放在两个不同的接口中,将行为逻辑隔离.
    public interface FirstFieldChangeMonitoring extends MonitoringFieldChange<FirstModel> {
    
    	void nameChangeMonitor(String oldName, String newName);
    
    
    	default Class<?> type() {
    		return FirstModel.class;
    	}
    }
    
    public interface FirstFieldWorkMonitoring extends MonitoringFieldWork<FirstModel> {
    	void workByWorkField(boolean work);
    
    	default Class<?> type() {
    		return FirstModel.class;
    	}
    }
    
    
    • 实现以及调用
    public class FirstFieldChangeMonitoringImpl implements MonitoringInterface<FirstModel>, FirstFieldWorkMonitoring, FirstFieldChangeMonitoring {
    	@Override
    	public void nameChangeMonitor(String oldName, String newName) {
    		System.out.println("数据变更" + oldName + "\t" + newName);
    	}
    
    	@Override
    	public void filedChange(FirstModel firstModel) {
    		this.nameChangeMonitor("", firstModel.getName());
    	}
    
    	@Override
    	public void workByWorkField(boolean work) {
    		if (work) {
    			System.out.println("开始工作");
    		}
    	}
    
    	@Override
    	public Class<?> type() {
    		return FirstModel.class;
    	}
    
    	@Override
    	public void fieldWork(FirstModel firstModel) {
    		this.workByWorkField(firstModel.isWork());
    	}
    
    	@Override
    	public void monitor(FirstModel firstModel) {
    		SupperMonitor<FirstModel> firstModelSupperMonitor = new SupperMonitor<>(firstModel, this, this);
    
    		firstModelSupperMonitor.monitor();
    	}
    
    	public static void main(String[] args) {
    		FirstFieldChangeMonitoringImpl firstFieldChangeMonitoring = new FirstFieldChangeMonitoringImpl();
    		FirstModel firstModel = new FirstModel();
    		firstModel.setName("aaaaaa");
    		firstModel.setWork(true);
    		firstFieldChangeMonitoring.monitor(firstModel);
    	}
    }
    
    
    • 接下来就是一个配合使用的技巧. 先做出第二个对象的一个监控实现
    
    public interface SecondFieldWorkMonitoring extends MonitoringFieldWork<SecondModel> {
    	void workByWorkField(boolean work);
    
    	default Class<?> type() {
    		return SecondModel.class;
    	}
    }
    
    
    public class SecondFieldWorkMonitoringImpl implements SecondFieldWorkMonitoring {
    	@Override
    	public void workByWorkField(boolean work) {
    		System.out.println("第二个 model 的 work");
    
    	}
    
    	@Override
    	public void fieldWork(SecondModel secondModel) {
    		this.workByWorkField(secondModel.isWorking());
    	}
    }
    
    
    • 补充监控字段, 测试和实现如下
    
    public class FirstFieldChangeMonitoringImpl implements MonitoringInterface<FirstModel>, FirstFieldWorkMonitoring, FirstFieldChangeMonitoring {
    	public static void main(String[] args) {
    		FirstFieldChangeMonitoringImpl firstFieldChangeMonitoring = new FirstFieldChangeMonitoringImpl();
    		SecondModel secondModel = new SecondModel();
    		secondModel.setWorking(false);
    
    		FirstModel firstModel = new FirstModel();
    		firstModel.setName("aaaaaa");
    		firstModel.setWork(true);
    		firstModel.setSecondModel(secondModel);
    
    		firstFieldChangeMonitoring.monitor(firstModel);
    	}
    
    	@Override
    	public void nameChangeMonitor(String oldName, String newName) {
    		System.out.println("数据变更" + oldName + "\t" + newName);
    	}
    
    	@Override
    	public void filedChange(FirstModel firstModel) {
    		// 字段变动任务
    		this.nameChangeMonitor("", firstModel.getName());
    	}
    
    	@Override
    	public void workByWorkField(boolean work) {
    		if (work) {
    			System.out.println("开始工作");
    		}
    	}
    
    	@Override
    	public void workBySecondField(SecondModel secondModel) {
    		SupperMonitor<SecondModel> secondModelSupperMonitor = new SupperMonitor<>(secondModel);
    		secondModelSupperMonitor.monitor();
    	}
    
    	@Override
    	public Class<?> type() {
    		return FirstModel.class;
    	}
    
    	@Override
    	public void fieldWork(FirstModel firstModel) {
    		// 字段行为任务
    		this.workByWorkField(firstModel.isWork());
    		this.workBySecondField(firstModel.getSecondModel());
    	}
    
    	@Override
    	public void monitor(FirstModel firstModel) {
    		SupperMonitor<FirstModel> firstModelSupperMonitor = new SupperMonitor<>(firstModel, this, this);
    
    		firstModelSupperMonitor.monitor();
    	}
    }
    
    
    
    • 这是目前笔者的一个想法. 各位阅读者如果有想法请在评论中告知. 大家是如何考虑这个逻辑的.
    第 1 条附言  ·  2020-09-24 14:20:36 +08:00

    网上找了一些相关文档, 收集了帖子中各位给出的意见, 整理了一下内容如下 https://www.yuque.com/huifer/mlnngl/vmgmq1

    5 条回复    2020-09-23 22:08:59 +08:00
    zhuangzhuang1988
        1
    zhuangzhuang1988  
       2020-09-23 13:27:58 +08:00
    aragakiyuii
        2
    aragakiyuii  
       2020-09-23 13:32:23 +08:00
    Proxy? 类似于 JPA 的 Entity 和 Spring 中 AOP
    huifer
        3
    huifer  
    OP
       2020-09-23 13:35:46 +08:00
    @aragakiyuii 目前业务层面还是直接调用具体的 service+method , 设计上面还是采用的上文所述的哪种方式再进行开发
    crclz
        4
    crclz  
       2020-09-23 14:37:06 +08:00
    你的思路非常不错。但是已经有大佬想到更好的东西: [领域驱动设计] 的 [领域事件] 。

    领域事件一般在调用实体方法时,被添加到实体的领域事件列表上,并在持久化时被发布和消费。

    对于下列你提到的应用场景,领域事件都很擅长:(
    字段变动.
    常见新老数据变更的日志记录
    字段直接会产生行为
    发消息的场景.填写了用户 id 就发送消息


    java 示例: https://github.com/e-commerce-sample/ecommerce-order-service
    Elroooo0Y
        5
    Elroooo0Y  
       2020-09-23 22:08:59 +08:00
    没看懂想干嘛 , 问题再描述的更清楚一下 .
    代码太多了 ,还是着重说下想法吧 .
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5518 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 08:16 · PVG 16:16 · LAX 01:16 · JFK 04:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.