- Algorithm
- Review
- 单例设计模式Singleton Design Pattern
- Spring bean作用域Bean scopes
- Tips:Mybatis Generator
- Share:行走江湖,脚踏实地
-
code (https://github.com/drejrnal/arts/blob/master/Artsweekone/WordSearch.java)
-
solution: 本题涉及到的知识点是回溯算法和前缀树;
- Board变量是一个二维数组(字母格),类似于迷宫问题,在某一时刻处在方格位置p时,下一时刻可分别移动到p的上、下、左、右, 因此每个位置会产生4种可能,这与图深度优先搜索方式类似,一次遍历过程中已走过的位置不能再触及,因此有visit的布尔型变量记录某一位置在前一时刻是否已遍历?亦可采取对board数组进行修改,从而达到相同效果(遍历某一位置后,置该位置board值为“#”,一次遍历完成后恢复原来的值),进而降低额外空间复杂度。
- 在递归过程中,除了可根据当前位置是否越界及之前是否遍历过从而终止递归调用,还可根据从开始到当前位置组成的字符串是否有可能会出现在目标字符串数组中?若不能,即当前组成的字符串不是目标字符串数组中任一前缀,亦可提前终止递归,从而降低时间复杂度。这种思想可借助前缀树加以实现。
-
complement
- 前缀树的实现可根据不同的需求对树中节点的属性进行定制或取舍,属性可包括以当前字符结束的字符串、以当前字符结束的字符串个数、是否以当前字符串结尾等。
- 在算法实现过程中,先后使用了HashMap和Node[]作为节点的children属性,提交后二者运行时间有差异。如果对前缀树搜索的操作频率过多,建议使用Node数组表示子节点。
在实际开发过程中,如果想确保在任何情况下都绝对只有一个实例,或在程序中表现出只有一个实例,此时就要用到单例模式(Singleton)。比如我们需要有一个管理多个资源的Manager实例。在Java实现中根据性能需求有两种实现方式
- Lazy initialization 直到程序中需要该实例,才会被创建
- Eager initialization 不管程序是否需要,该实例均会被创建,适用于实例创建代价较小,或者前提已知程序会频繁用到该实例。
一般会通过Class.getInstance()获取实例。 单例设计模式中注意线程安全问题,由于只有一个实例,当有多个线程访问实例中资源的时候,可能会产生可见性问题,因此对于某些方法或代码块需要添加synchronize。
在理解了单例设计模式思想后,对于Spring中bean的作用域又有了新的认识。 首先原文提到
when you create a bean definition what you are actually creating is a recipe.Then you can potentially have many instances created from a single recipe.
在定义bean的过程中可以设置bean的作用域,Spring bean的作用域有5种,
- singleton
- prototype
- request
- session
- global session 其中后三者只有使用Web aware ApplicationContext时才可用。
个人理解为当bean definition 写好后,bean lifecycle、Bean configuration、Bean scope信息已经生成,此时spring container根据bean作用域是singleton或prototype来产生一个或多个实例。同时container还会根据bean实现了哪些与生存周期的创建相关的接口进一步初始化bean实例,用于程序中其他地方使用。 注意同传统的单例模式不同,单例作用域范围仅限于同一个Spring container,如果有多个container,各个container都会产生的实例就不同。spring doc中有这样一句话:When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.这说明如果定义bean时采用不同的ID,即使指向的是同一个bean class,IOC container也会为每个ID创建一个实例。即不同的ID对应不同的实例,相同的ID共享同一个实例。
对于Request scope和session scope,对于每次http的请求,Spring container都会创建一个新的实例,对于实例内部的状态你可以随意改变,因为创建的实例之间是相互独立,相互隔离的。当请求结束后,bean就会被discard掉。
MyBatis Generator是一个可以用来生成Mybatis dao,entity,Mapper文件的一个工具,在项目的过程中可以省去很多重复的工作,我们只要在MyBatis Generator 的配置文件中配置好要生成的表名与包名,然后运行一条命令就会生成一堆文件。在实际开发过程中,常需要将自动生成的目录与手动生成的目录分开,便于功能的拓展,使 的代码可维护性更好。如果使用maven构建项目的时候,使用mybatis-generator-maven-plugin插件自动生成MyBatis代码。
皓叔对于高效率的学习见解让我触动颇深,其中提到了学习并不是努力读多少书,追求阅读的速度和数量;看书、听课、别人演示都不能让你真正获得学习能力;只有开始同别人交流、总结归纳、主动输出才能获得质的提升。
这让我回忆起前不久研究生复试时的场景:当面试老师让我说出系统调用和中断有哪些区别时,紧张的我第一条就说了二者都涉及到进程切换。结束后我翻看了极客时间某一专栏,其中提到系统调用始终是一个进程在运行,会涉及CPU上下文切换,因为牵涉到特权模式即用户态和内核态的切换,但并不是进程上下文切换;中断会打断当前正在运行的进程,转而执行中断处理程序,其中也不会涉及保存进程用户态上下文的过程,只会设计内核态上下文保存与加载。
我开始反思:很多概念都学过,却不能在高度紧张的状态下清晰索引定位并能够流利表达,概念与概念之间的联系、对比并没有下功夫去深究。根本原因在于本科期间与人交流太少,总是自己看书,观点没有输出,也很少询问别人的看法;另外一方面在于学习时不善于系统总结,由此及彼、由表及里。这点在操作系统和体系结构方面尤为突出,加之缺乏实际操作经验,许多知识就像空中楼阁,时而出现,时而虚无缥缈,所以出现了在面试时紧张状态下大脑一片空白的场景。
人在江湖,要学会主动吸收其他门派(职业)、高手的思想和见解,不能固步自封;更要学会与别人交流,通过不断的反馈完善自己的认知结构。
在群里看到了一位同学分享了一篇关于技术人成长的文章,文中提到了一位从业数年的程序员回首过往,希望做出改变的是认真学习C语言,进而研究操作系统、编译器设计和网络编程。我曾经尝试过阅读TCP/IP、Unix系统编程类的书,但总是因为C语言基础不牢,阅读程序吃力,文字理解也有些许困难,最后不了了之。皓叔在程序员练级攻略中也谈到对于系统方面的知识理解,需要动手写点小程序或完成实践项目,我觉得无论是今后的发展还是出于个人兴趣,我应该重新认识C语言并且需要重启之前半途而废的进程。武林高手们都需要某一段长时间的闭关修炼继而灵魂蜕变,功力突破;程序员的成长大概也要经历这种类似的磨炼吧!
与诸君共勉