在公共函数中区分上层调用者的模型

本文探讨了在编程中如何区分上层调用者的需求,通过设置全局标志变量来处理UI界面刷新按钮和DOM事件委派等场景。作者详细介绍了在SlickGrid框架中处理刷新功能和自定义select控件时遇到的问题,以及如何通过flag来区分不同的调用流程。同时,提出了模型的扩展和遗留问题,包括input事件、keyup事件以及公共函数与下层函数调用的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景及问题详述:

  在编码时常常会将多次用到的公共函数封装之后,供其他函数调用。而在调用时,免不了需要根据上层调用函数的不同有不同的结果。
  举几个最近遇到的具体的场景:

1.UI界面的刷新按钮

  UI界面的刷新按钮,其功能定义不同于F5的刷新整个页面。而是通过给定的url再次获取页面中指定的表格数据、图片等。以表格为例,为方便用户操作和减轻前端压力,表格常常会有分页、搜索功能。当存在分页功能时,搜索就必须后台处理(除非你想实现这样的效果————只告诉用户当前页有几项匹配,即使在后台保存的数据中存在其他的匹配项,也忽略),此时每一次搜索、翻页都是通过url请求数据来实现的。那刷新按钮需要实现的功能就是,记录最近一次的请求,点击刷新时重新获取一次数据。
  按理说实现起来简单啊,用个变量保存最近使用的url就好了,刷新就取这个变量再请求一次。的确,如果自己从头写请求,写表格的展现方式,这不失为一种解决方式。但我想现在很少有人在工作中会从头写,都是使用第三方的js库。比如,笔者在项目中使用的就是基于SlickGrid(https://github.com/mleibman/SlickGrid)再次封装的框架,该框架不支持动态传入url,取代的是在创建时指定一个baseUrl,在load数据时调用此url,之后若需要实现过滤效果,则需传入一个filter对象(JSON形式),由其内部拼装成baseUrl?key=value&name=tom的形式,再调用此url,可气的是封装好的对象不返回当前使用的url。
   当时为了解决此问题,考虑过修改框架,增加一个方法,将当前使用的url暴露出来。当然这是最后的方法,因为太蠢太暴力。之后详细分析代码,发现两条流程有差异,也有联系。正常获取时,走load方法;过滤时需要先自行拼装json并传入对象,最后还是会调用load方法。
  最后采用设置一个变量flag并初始化为false,当走过滤时,将flag置为true,并保存filter对象,在load执行时的回调函数中,先根据flag的值判断是过滤流程还是直接获取,在处理完相应业务后,再将flag置false。
  整个流程中flag最终都会被置为false,唯一flag为true的时候就是经过过滤,业务处理完之前。
  之前的刷新实现就是根据flag值判断是过滤还是直接获取后,用同一个函数封装处理如过滤则

        func = function(){
                    obj.setFilter(filter);
                    obj.load();
                }
                func = function (){
                    obj.load();
                }

  最后点击刷新时直接调用函数func();

2.DOM元素事件委派

  同样是使用封装过的控件(公司内部使用,样式统一,因信息安全问题无法贴代码),因原生select丑爆了且不可编辑,在封装select控件时,隐藏了select,以input显示,同时在功能上即支持用户下拉选择(通过css样式和事件委派,使用隐藏的select实现),也可支持用户输入(input实现),即界面显示的是一个有着select功能和视觉效果的input框!
  感觉屌屌的,马上问题就来了——参数检查。禁用input的输入还好,选什么就显示什么,怎么检查都好。但同时支持选择和输入时,检查就有问题。监听select的select事件,此事件触发时只是选中了,但值还没有填到input中,只能通过检查select的值来检查。而input的input方法(为了能感知到用户用鼠标复制黏贴而监听的input事件)因为用户输入的,肯定是取input的值检查合理,input事件处理完后会再执行select的select事件(因为有一个小功能,根据输入的input值会匹配下拉框现有的值,类似于百度搜索输入)。此时select用自己的逻辑检测并覆盖之前input的结果。然后悲剧。
  最后同例一一样使用一个flag用以在公共的函数select中判断是哪个流程调用了该方法。区分执行各自的逻辑。

二、模型说明

  抽取公共部分分析:
这里写图片描述
  全局定义flag=false,在每次公共函数结束时将flag置为false,flag只有在经过特性函数,且未退出公共函数时才为true,以此判断这一次流程是否走过特性函数。流程可反复循环的调用。
  将flag换为整数,可以区分多个特性分支到底走了哪条。
  这里写图片描述

三、扩展和遗留问题

1.input的input事件

该事件在标准浏览器中良好支持,IE9以下不支持。需使用IE专用属性onpropertychange
oninput事件在value改变且失去焦点时实时触发,但是通过js改变value时不会触发;
onpropertychange事件是任何属性改变都会触发,每增加或删除一个字符就会触发,通过js改变也会触发该事件

2.keyup事件

keyup事件未参数检测常用的事件。但经测试,该事件在select之前和之后各触发一次。不适用该模型

3.相似模型讨论

先调用公共函数,在调用下层函数(也可能没有下层函数)。
目前有两条思路:
  公共函数处理一遍,若有下层函数,推翻公共函数的结论,以下层函数结果为准(无脑覆盖流)。缺陷,过渡过程有时让人难以接受。还是以参数检测为例,先显示错误提示,再检测一次,发现合法,再隐藏,表现就是用户输入一个字符,错误提示闪一下又没了,坑。
  为了解决上面的问题。考虑过再公共函数中使用一个定时器,我得到结果,但我傲娇,我要等一段时间(比如20ms)在将结果反馈展现。如果后续的下层调用者赞同我,以我的结果为准,定时器超时后显示结果,如果下层调用者结果与我不同,取消定时器,由下层调用者显示结果。(公共函数:意见一致时,我说了算,不一致时,别人说了算~)。
  

4.缺陷与待思考、优化点

只适用于单线程,目前在前端使用足够。但该模型在多线程时需注意同步互斥,具体可参考操作系统关于信号量的表述。
公共函数本身的立意是处理相同的逻辑,现在需在其中根据特性实现不同的功能,实际以违背了最初的用意,若代码全为自己实现,应考虑将对特性的区分处理抽取出来,独立处理。
### DAO层与Entity层的关系分析 在软件设计中,DAO(Data Access Object)层和Entity层之间的关系可以从功能职责和设计模式两个方面进行深入剖析。 #### 1. 功能职责上的区分 - **Entity 层** Entity 类通常是 ORM(对象关系映射)框架的核心组件之一,其主要职责是定义数据库表的结构并封装业务数据。这些类通常遵循 JavaBean 规范,提供无参构造函数、私有字段以及公共 getter 和 setter 方法[^1]。它们的主要目标是对现实世界中的实体建模,并作为数据容器存在。 - **DAO 层** DAO 层的作用则是抽象出对底层数据库的操作细节,使得上层调用者无需关心具体的数据访问技术或 SQL 查询语句。它的核心任务包括执行 CRUD(创建、读取、更新、删除)操作以及其他特定查询逻辑[^2]。 #### 2. 关系判定:依赖 vs 组合 - **依赖关系** 如果 DAO 层需要使用 Entity 对象来进行数据交互,则表明二者之间存在一种典型的“依赖”关系。在这种情况下,DAO 层依赖于 Entity 层所提供的数据模型来完成相应的持久化操作。例如,在 Hibernate 或 JPA 中,DAO 方法可能会接收或者返回 Entity 对象实例[^3]。 - **组合关系** 组合关系意味着一个对象完全拥有另一个对象的生命期控制权;然而,在标准的分层架构下,DAO 并不会直接管理 Entity 的生命周期,而是通过事务管理和上下文环境间接影响其实例状态变化。因此严格意义上讲,DAO 层与 Entity 层并不构成真正的组合关系[^4]。 综上所述,DAO 层与 Entity 层更多体现的是 **依赖关系** 而非组合关系。 ```java // 示例代码展示 DAO 如何依赖 Entity public class UserDao { public void save(User user) { // User 是 Entity 类 entityManager.persist(user); } public List<User> findAll() { return entityManager.createQuery("FROM User", User.class).getResultList(); } } ``` ### 设计差异对比 | 特性 | DAO Layer | Entity Layer | |-----------------|------------------------------------|----------------------------------| | 主要责任 | 数据库操作 | 表示业务领域内的对象 | | 生命周期管理 | 不直接参与 | 受限于当前会话/事务范围 | | 抽象级别 | 较高 | 基础 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值