代码要写成别人看不懂的样子(十七)

第十七届中国计量大学程序设计竞赛B Broken Pad ---python 第十七届中国计量大学程序设计竞赛B Broken Pad B **题意:**油腻的叔叔在打牌,胖宅男在吃饭…咳 就是输入两个数组,一个a,一个b,问点击哪几个位置可以将a变成比b,要求点击最少次。 **PS:**点击的是位置不是下标,点击0就全部清零,而点击对应位置则该位置及以后的数全都取反。 英语好的麻烦自己读题,就都这个题目,废了老大鼻子的劲。 思路: c++的没看懂 python做的话基本思路就是异或,然后按位取反,但是真的每次都按位取反输出内存会爆,所以记录一个变量bool,在奇数次翻转时,a 阅读详情

本篇文章参考书籍《JavaScript设计模式》–张容铭

前言

  各位作为一名前端开发,大家有没有遇到过前端存储,比如用户初次进入程序,会有一个个性化引导,一般来说这块功能是交给后台同事来做的,但是有时候需要放在前端,来保存是否第一次登陆的字段。

  那我们在本地存储的时候呢,可能会遇到很多问题,每添加一组数据,担心会不会覆盖别人的数据等等,本节的设计模式,就介绍怎么合理前端存储。

数据访问对象模式

  抽象和封装对数据源的访问与存储, DAO通过对数据源链接的管理方便对数据的访问与储存。

  我们可以创建一个数据访问对象类,来解决上面的问题。这个数据访问对象类是对本地存储的一次封装,要创建 DAO 类,首先要了解当前的需求,最好也顾虑一下其他人的需求,这样创建的 DAO 类才更加健全。

  首先,我们的数据需要有增,删,改,查的功能,其次当别人使用本地存储的时候,也需要知道我保存了哪些数据。

  本地存储使用的是 localStorage 这个对象,对于同一个站点,里面根本没有分割库,所以所有人用的 localStorage 都是同一个,所以应该将每次存储的数据前面字段前面添加字段标识来分割 localStorage 库,

  本地存储对数据的保存实际上是 localStorage 的一个字符串属性,有时对于存储来说,了解它的时间很重要,能方便日后的管理,因此我们还需要一个时间戳。

/**
* 本地存储类
* 参数 preId    本地存储数据库前缀
* 参数 timeSign 时间戳与数据之间的拼接符
*/
var BaseLocalStorage = function(preId, timeSign) {
	//定义本地存储数据库前缀
	this.preId = preId;
	//定义时间戳与数据之间的拼接符
	this.timeSign = timeSign || '|-|';
}

  为了知道数据的状态,我们可以在 DAO 类内部保存操作返回状态供肉厚使用时调用,我们还需要将本地存储服务的引用保存在 DAO 类的内部以方便我们使用。当然 DAO 类还需要提供对数据库的增删改查操作接口方法。

//本地存储类原型方法
BaseLocalStorage.prototype = {
	//操作状态
	status: {
		SUCCESS: 0,   //成功
		FALLURE: 1,   //失败
		OVERFLOW: 2,   //溢出
		TIMEOUT: 3,   //过期
	},
	//保存本地存储链接
	stroge: localStorage || window.localStorage,
	//获取本地存储数据库真实字段
	getKey: function(key) {
		return this.preId + key;
	},
	//添加(修改)数据
	set: function(key, value, callback, time) {
		//省略操作
	},
	//获取数据
	get: function(key, callback) {
		//省略操作
	},
	//删除数据
	remove: function(key, callback) {
		//省略操作
	}
}

  我们下面的事,只要实现 set , get , remove 就可以了。首先是 set 方法,我们需要在字段中添加时间戳,我们向本地存储中添加的数据实质上事调用 localStorage 的 setItem 方法。最后我们还要执行回调函数并将操作的结果传入回调函数中。

/**
* 添加(修改)数据
* 参数 key      数据字段标识
* 参数 value    数据值
* 参数 callback 回调函数
* 参数 time     添加时间
*/
set: function(key, value, callback, time) {
		//默认操作状态时成功
	var status = this.status.SUCCESS,
		//获取真实字段
		key = this.getKey(key);
	try {
		//设置参数时获取时间戳
		time = new Date(time).getTime() || time.getTime();
	} catch (e) {
		//未传入时间参数或时间参数有误获取默认事件:一个月
		time = new Date().getTime() + 1000 * 60 * 60 * 24 *31;
	}
	try {
		//向数据库中添加数据
		this.storage.setItem(key, time + this.timeSign + value);
	}catch (e) {
		//溢出失败,返回溢出状态
		status = this.status.OVERFKOW;
	}
	//有回调函数则执行回调函数,并传入参数操作状态,真实数据字段标识以及存储数据值
	callback && callback.call(this, status, key, calue);
}

  有了设置数据方法,通过存储字段获取数据的方法也就简单了,还是调用 localStorage 的 getItem 方法,不过需要注意是,这里兼容了四种查询数据的情况,第一种,该字段数据本来就不存在,这样应该返回失败状态;第二种,操作成功但没有获取到值,此时也应该返回失败;第三种,获取到值了,但是时间已经过期了,此时应该删除该数据;最后一种,成功获取数据并成功返回。

/**
* 获取数据
* 参数 key      数据字段标识
* 参数 callback 回调函数
*/
get: function(key, callback) {
		//默认操作状态时成功
	var status = this.status.SUCCESS,
		//获取
		key = this.getKey(key),
		//默认值为空
		value = null,
		//时间戳与存储数据之间的拼接符长度
		timeSignLen = this.timeSign.length,
		//缓存当前对象
		that = this,
		//时间戳与存储数据之间的拼接符起始位置
		index,
		//时间戳
		time,
		//最终获取的数据
		result;
	try {
		//获取字段对应的数据字符串
		value = that.storage.getItem(key);
	} catch (e) {
		//获取失败则返回失败状态,数据结果为null
		result = {
			status: that.status.FAILURE,
			value: null
		};
		//执行回调并返回
		callback && callback.call(this, result.status, result.value);
		return result;
	}
	//如果成功获取数据字符串
	if(value) {
		//获取时间戳与存储数据之间的拼接符起始位置
		index = value.indexOf(that.timeSign);
		//获取时间戳
		time = +value.slice(0, index);
		//如果时间为过期
		if(new Date(tiem).getTime() > newDate.getTime() || time == 0) {
			//获取数据结果(拼接符后面的字符串)
			value = value.slice(index + timeSignLen);
		} else {
			//过期则结果为null
			value = null;
			//设置状态为过期状态
			status = that.status.TIMEOUT;
			//删除该字段
			that.remove(key);
		}
	} else {
		//未获取数据字符串状态为失败状态
		status = that.status.FAILURE;
	}
	//设置结果
	result = {
		status: status,
		value: value
	};
	//执行回调函数
	callback && cakkback.call(this, result.status, result.value);
	//返回结果
	return result;
}

   remove 方法照猫画虎,首先删除应该用 localStorage 的 removeItem 方法。执行时会有 3 中状态,第一种,没有修改字段,这样操作结果是失败状态,第二种情况是删除(调用 removeItem 方法) 时发生异常,这样也应该是失败,最后一种当然就是修改成功。

/**
* 删除数据
* 参数 key      数据字段标识
* 参数 callback 回调函数
*/
remove: function(key, callback) {
	//设置默认操作状态为失败
	var status = this.status.FAILURE,
		//获取实际数据字段名称
		key = this.getKey(key),
		//设置默认数据结果为空
		value = null;
	try {
		//获取字段对应的数据
		value = this.storage.getItem(key);
	} catch (e) {}
	//如果数据存在
	if(value) {
		try {
			//删除数据
			this.storage.removeItem(key);
			//设置操作成功
			status = this.status.SUCCESS;
		} catch (e) {}
	}
	//执行回调,注意传入回调函数中的数据值:如果操作状态成功则返回真实的数据结果,否则返回空
	callback && callback.call(this, status, status > 0 ? null : value.slice(value.indexOf(this.timeSign) + this.timeSign.length))
}

  这样我们的整个 DAO类 就完成了,接下来测试一下。上面有一个小技巧不知道大家发现没有,我们在设置默认状态的时候, set 和 get 默认操作是成功,而 remove 的操作状态却是失败,这是为什么的?

  这是因为我们在设置默认状态的时候,应该保证默认状态尽可能多的出现,这样我们的代码执行效率会高一些,这也体现了一个工程师对自己设计的代码的一个全局把控能力。

var LS = new BaseLocalStorage('LS__');
LS.set('a', 'xiao ming', function() {console.log(arguments);});  //[0, "xiao ming", "LS__a", "xiao ming"]
LS.get('a', function() {console.log(arguments);});      //[0, "xiao ming"]
LS.remove('a', function() {console.log(arguments);});   //[0, "xiao ming"]
LS.remove('a', function() {console.log(arguments);});   //[1, null]
LS.get('a', function() {console.log(arguments);});      //[1, null]

  对于不支持本地存储的浏览器,我们有时会通过 cookie 或者浏览器 userData 存储区存储数据,这就需要对我们的 DAO 进行重构,兼容更多浏览器,重构方法可以用我们之前学习到的设计模式,各位就看你们的掌握程度了。具体大家可以当作一个练习题来做。




一个屌丝程序猿的人生(八十七)   公司来了新人,大家自然都非常关注,纷纷停下了手头的工作。   小魏则是先指着身材比较魁梧的哥们,介绍道:“这位是李魁,会跟着我一起做点NET开发的工作,大家欢迎。”   “啪啪啪.......”   一阵掌声响起。   林萧则是此时才反应过来,原来这个叫李魁的哥们,是跟着小魏做点NET的。   紧接着,小魏又一指另外一个哥们说道:“这位是王立新,会跟着程刚,还有程佳丽和林萧一起,做J... 阅读详情

相关推荐

咱们一起学C++ 第二百一十七篇之C++纯抽象类与纯虚函数的深度探索

大家好!在C++的学习道路上,我们不断接触到各种有趣且实用的概念,今天咱们来深入了解一下纯抽象类和纯虚函数。我在学习这些知识的时候,发现它们就像编程世界里的神奇工具,能帮助我们构建出更灵活、更强大的代码结构。希望通过我的分享,能让大家也轻松掌握这些知识,咱们一起进步!

wj_rdk的博客 1475

代码要写成别人看不懂的样子(三)

文章目录前言 前言   书接上回,我们学习了装饰器模式,不知各位道友是否还有印象,               

不见浅诗的博客 416

OpenCV轮廓匹配实战:5分钟搞定Hu矩形状识别(附完整代码)

本文详细介绍了使用OpenCV进行轮廓匹配的实战技术,重点讲解了Hu矩形状识别在工业质检等领域的应用。通过完整的代码示例和参数调优技巧,帮助开发者在5分钟内实现高效的形状识别,提升工业检测的准确性和效率。

nnn11的博客 675

代码要写成别人看不懂的样子(五)

文章目录前言一、外观模式二、适配器模式 前言   通过前面几篇文章,大家估计对对象的创建有了一个新的认识,在很多大型应用里面,对象会相当复杂,但是其刚创建的时候,并不是这样,而是通过后续的组合,封装,才一步一步完善起来的,从本章节开始,我们一块来学一学,如何把这些对象组合的更合理,从而使想强大的功能。 一、外观模式   大家一定绑定过事件,而且一定像下面这样绑定过 document.onclick = fucntion(e) { e.preventDefault(); if(e.target !== d

不见浅诗的博客 455

shader基于高度的权重混合

效果图: 基于高度的权重混合 , 效果描述: (1)混合:三层混合, 例如 第一层是草,第二层是石头,第三层是沙子,三者混合显示 (2)权重: 三层的权重的和 为1, 三者是此消彼长的关系 (3)高度:高度会限制或者说是 束缚 着 效果 关于混合,再多说几句: (1)基于权重的混合:权重 ,跟顺序没有关系 只跟权重的大小有关系(在一层一层界限不清晰的地方,特别适用!!效果极好!!!!) (2)基于叠加的混合: 叠加 就是 一层一层的往上加。。。。 所以顺序特别重要(在雪地等效果中使用:因为

木马人 1117

运放 + MOS管构成的恒流电路分析及实用环境器件参数选择

恒流电路

五花带点肉 2万+

如何写出同事看不懂的Java代码?

哈喽大家好啊,我是艾小仙。前几天,正巧赶上组里代码review,一下午下来,感觉整个人都血压拉满了。五花八门的代码让我不禁感叹,代码规范这条道路还是任重而道远…那么今天就来给大家总结一波Java中的代码作死小技巧,熟练掌握这些小技巧后,保证能让你写出同事看不懂的代码~至于为啥要写出同事看不懂的代码,通过这次教训,我发现好处还是挺多的,简单举几个例子:同事无法轻易修改你的代...

艾小仙的专栏 494

C语言专升本编程题

湖南省专升本选拔考试,C语言程序设计内部习题

weixin_45729947的博客 2115

Java小白也能轻松写一个大神都看不懂的程序,绝对让人佩服

你想在别人面前秀一把你的“神功”吗?跟着二当家的轻松学到“武功根基”,秀他们一脸的迷茫。

二当家的白帽子 2240

YOLOv11改进 | Conv/卷积篇 | 轻量化多尺度异构卷积(MSHC)优化YOLOv11精度(全网独家首发)

本文介绍了Hype-YOLO提出的MANet结构,这是C3、C2f、C3k2的升级版,能显著增强特征提取能力。MANet整合了DSConv和C2f结构,通过多分支异构设计提升梯度流动和特征语义深度。文章详细解析了MSHC模块的原理,包括其多尺度并行建模、通道混洗等核心机制,并提供了完整的代码实现和训练教程。实验表明,Hype-YOLO的精度优于YOLOv11。该结构在保持轻量化的同时,通过异构分支设计实现了更丰富的特征表达,适用于目标检测等视觉任务。

Snu77的博客 949

DeepSeek如何构建可扩展的 AI 驱动交易系统,基于 MetaTrader 5 与 Python 利用先进的数据处理、机器学习和容器化部署来优化算法交易。

MT5 Python API 架构设计分为三层:通信层:利用异步消息传递(例如 ZeroMQ 或标准套接字编程)支持每秒数万个数据请求。转换层: C++ 动态库有效地将 MT5 命令转换为 Python 对象(反之亦然),从而优化速度和内存使用率。接口层:提供Pythonic API,封装了所有终端功能,包括:1)实时价格订阅(滴答或秒级更新)2)历史数据检索(从M1到更高的时间范围)3)订单流监控(交易详情和市场深度)4)策略执行引擎(用于算法交易)

iCloudEnd的博客 1379

代码要写成别人看不懂的样子(九)

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言模板方法模式 前言   前几节的结构型设计模式,各位学的乱不乱,我个人刚开始接触的时候,也觉得很抽象,不太好理解,尤其是实战的时候,总是不知道在什么情况下使用。记住一点,当我们单纯的创建一个    模板方法模式       ...

不见浅诗的博客 397

WindowsServer2022蓝牙音频开启方法

为Windowsserver 2022 添加蓝牙音频驱动的方法和工具

thebestismin的专栏 2704

代码要写成别人看不懂的样子(二十七)

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言MVC 模式总个小结 前言   嗨!各位乡绅,上一节的字符串模板,有没有很崩溃,模板引擎写起来是有点费劲,但是思路比较简单,慢慢梳理就好。   本节我们来个硬货,如果各位经常浏览招聘信息,那么很多公司都会在岗位要求上面写上,熟悉 MVC 框架者优先。今天我们就来搞搞,到底什么是传说中 MVC 。 MVC 模式   MVC 即模型(model)—视图(view)—控制器(controller),用一种将业务逻辑、数据、视图

不见浅诗的博客 311

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

30天自制操作系统——第十七天制作命令行窗口

今天的任务是制作命令行窗口,那么命令行窗口应该是什么样呢? 在Windows系统里我们都使用过命令行窗口,它首先是黑底的,可以在里面输入各种字符、可以对输入的命令进行响应… 由于命令行窗口的制作用到的都是之前的知识点,难度并不大。由于修改的代码量较大,篇幅有限,就不把代码粘贴上来了,有兴趣的同学可以自行下载阅读。 这里主要记录一下制作命令窗口的关键步骤(本节没有什么新的知识点,可以直接跳过): 一、绘制命令行窗口 我们先在HariMain函数中画出一个命令行窗口的样子,命令行窗口一般就是黑底白字,可以对输入

mint1993的专栏 5275

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【逆向基础】十七、PE文件格式(二)

文本章详细讲解了PE文件头的信息。包括`Dos Header`,`Dos Stub`,`NT` `Header`,`Section Header`等四个主要部分,并列举了其中包含的结构体信息。通过注释,举例的方式快速帮助我们了解PE文件最初的样子。

幸福之家的博客 922

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

力扣练习第十七天——全排列

力扣练习第十七天——全排列 题目大致如下: 给定一个没有重复数字的序列,返回其所有可能的全排列 示例: 输入:[1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 链接来源于LeetCode:https://leetcode-cn.com/problems/permutations/ 大致思路: 最开始采用的是直接...

weixin_43873644的博客 220

关于动态函数的一点理解 — 《Dive Into Python》第十七章学习笔记

关于动态函数的一点理解  -  《Dive Into Python》第十七章学习笔记 平时的笔记都记录在书上,但这次的笔记太长,我准备打印出来用胶水粘到书上。0. 写在前面   如果你有机会看到这一章,你会发现他的标题是“动态函数”。也就是说:“本章要讲述面向函数的编程”这一概念。如果你想学习python有没有看过这一章,我强烈推荐你去看。Dive Into Python ...

SAP => Simplify Anything Possible 189

优快云 编程竞赛十七期题解

优快云 编程竞赛十七期题解

互关互助互赞,共同进步 6327

Java入门(十七)

Java入门(十七) Arrays类 在数组中,并没有什么方法可以供我们使用,只有array.length可以用。我们自己写一个方法去遍历、反转数组。 那么Java在数组方面给我们提供了一个java.util.Arrays的类。用这个类可以进行一些操作。 Arrays类包含操作数组方法,如果数组为空,他就会抛出异常 里面有许多的方法,都是以static开头的。我们可以直接调用 要去学习一个类,可以点进去类里面看一下源码。点击structure binarySearch是二分查找法,fill可以直接把

qq_42938493的博客 138

第十七、Java面向对象之构造函数与构造代码块

我们人出生的时候,有些人一出生之后再起名字的,但是有些人一旦出生就已经起好名字的。那么我们在java里面怎么在对象一旦创建就赋值呢? 需求: 使用java类描述 一个婴儿, 一种婴儿一出生就具备了名字(白户),还有一种婴儿就是 出生之后才有名字 的(黑户)。 构造函数的作用: 给对应的对象进行初始化。 构造函数的定义的格式: 修饰符  函数名(形式参数){ 函数体

iOS小菜鸟的专栏 560

高中Up主200天肝出偷懒机器人!可拎包,全场景跟随,已获百万播放

博雯 萧箫 发自 凹非寺量子位 报道 | 公众号 QbitAI难以想象,这竟然是一个18岁高中生独立做出来的机器人!无论室内外,都能实现跟踪:就连在黑夜里跟着走,也No problem:当...

量子位 364

TowardsDataScience 博客中文翻译 2022(三十七)

从我的经验来看,我想强调的是,这只是我的拙见,从一开始就使用这种模式通常是个好主意,甚至是 MVP。这听起来可能更复杂(事实也确实如此),但是当你得到这个钻头时,它是一个不需要动脑筋的东西,并且可以灵活地进行你以后可能想要添加的任何进一步的修改。然而,关注注入的依赖项的数量也是一个好主意——您不希望它增长太多。我个人发现的最常见的缺点是代码变得难以理解,尤其是当团队中有新成员加入时。但是,通过适当的入职培训,这个问题很容易解决:收益大于成本。

龙哥盟 1490

js系列十七:纯函数

相同的输入总会得到相同的输出,并且不会产生副作用的函数,就是纯函数。 我们可以通过一个是否改变原始数据的两个同样功能的方法来区别纯函数和非纯函数。 我们期待封装一个函数,能够获取传入数组的最后一项。那么可以通过一下两种方式 function getLast(arr){ return arr[arr.length]; } function getLast_(arr){ return arr.p...

人生代码 ---- 公众号 3081

第十七届全国大学智能车竞赛总决赛线下比赛颁奖照片

第十七届全国大学智能车京赛闭幕式颁奖仪式

TSINGHUAJOKING 1776
上一篇: 代码要写成别人看不懂的样子(十六)
下一篇: 代码要写成别人看不懂的样子(十八)
不见浅诗~
博客等级 码龄7年 506粉丝 129原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值