本周的课程主要讲解设计模式。
在上周的总结中,我曾提到:
为了避免编写出“坏味道”的代码,前人经过总结得出了面向对象编程的几大设计原则,并进一步总结出了三大类、23种设计模式。无论设计原则还是设计模式,本身都是跟语言无关的,设计原则是编写代码的通用最佳实践,而设计模式是针对特定某类问题的通用解决方案。设计模式最终的目的是为了满足设计原则。
所谓模式,其实就是一种“套路”,因此设计模式是是编程领域数十年来智慧的结晶,是经历过无数次实战检验的行之有效的方法集, 其核心思想和目标是尽可能增强代码的复用性和适应性,减少代码修改的次数和范围,使代码更便于组织和维护。“设计模式”这一术语最早源于GoF编写的《设计模式》这本书,其中总结了三大类、23种设计模式,这本书诞生于1993年,随着软件行业的不断发展、需求的不断变化,以及软件系统结构的不断更迭,人们在这23种设计模式的基础上又扩充出了更多针对特定领域、特定架构的设计模式。同样,面向对象的设计原则也在SOLID的基础上得到了扩充,加入了LoD、KISS、DRY、YAGNI等等原则。
我对设计模式的理解是,设计模式提供了一系列套路性的编程模版和方法,帮助开发者更好地实现面向对象的设计原则。由于每种设计模式都有特定的名称和对要解决的问题的描述,并且名称和描述是得到行业公认的,因此针对特定的要解决的问题,只要找到与之相对应的设计模式,遵照该模式所提供的解决方案,即代码的结构模版和逻辑模版来编写代码,就能够很好地利用面向对象的思想和原则来解决该问题。
另外,我认为设计模式是方法论,但实际应用中我们不能强行去套模式,把设计模式当作规范一样去实施,这样可能反而会出现画蛇添足、本末倒置的情况。在学习设计模式的时候我们更应当理解其背后的思想和体现的面向对象设计原则和方法,为什么我们应当用这样的方法来解决问题,它的好处在哪里。在剥离了具体语言实现的情况下来思考这样的问题,才能有助于我们更好地理解设计模式到底是用来做什么的。我认为它更多的是一种锻炼思维的方式,狭义上讲它是用来编写高内聚、低耦合、可扩展的面向对象代码的参考套路,而从广义上讲它可以用来解决我们工作、学习和生活中遇到的任何问题,因为面向对象思想本身就是对现实世界的模拟、抽象和简化。
在实际工作中,通常是多个设计原则和设计模式同时使用的,但无需刻意地去遵循某些原则和模式, 应当根据实际情况来灵活调整。总体来说,多利用封装、继承、多态机制,实现代码的可扩展性和可复用性,这就是设计模式的体现。
标准的23种设计模式被分为了创建模式、结构模式、行为模式三大类,分别对应于处理对象实例化相关问题的模式、处理类和对象之间关系的模式、处理对象行为过程的模式。设计模式其实早已潜移默化地被应用于日常的编程中,只是我们没有意识到而已。例如我们最常使用到的就是单例模式、工厂模式、观察者模式。
单例模式
单例模式指的是确保无论对某个类执行多少次实例化操作,都只能得到一个实例。单例模式可以避免实例的重复创建,减少频繁创建和销毁实例所带来的资源消耗,另外也可以确保不同对不同的调用方进行统一的控制。
在实际工作中,单例模式常被用于创建数据库连接对象、第三方API连接对象、代理对象等,因为这些对象创建一个和创建多个的作用是一样的,没有必要重复创建,一直用同一个实例就行了。不过这里引出来了一个问题,就是在并发环境下,多个并发任务同时去调用单例时是否会造成冲突,如果有冲突要如何解决,这里可以使用锁、队列等方法,另外,我们应当尽量把单例设计为无状态的对象,避免在单例中直接保存状态。
看上去,单例模式显然是属于创建型的设计模式,但其实我们会发现在实际工作中还有更多体现着单例思想的地方。例如各种网盘的“秒传”功能,其实就是在上传之前识别一下待上传文件的特征值是否已经记录在系统中,如果是的话说明同样的文件此前已经由其他用户上传过,因此就不用再重复上传了,直接新建一个指向之前上传的文件的引用就可以了。再比如很多付费会员服务为了避免被盗用,不允许同时在多台设备(更多情况是同类设备)上登录,这也体现了单例模式的思想。
工厂模式
工厂模式同样属于创建型模式,它同时体现了封装、多态特性和开闭原则,其根本思想就是对调用方隐藏对象的具体创建过程,调用方只需通过工厂所提供的固定接口就可以拿到自己所需要的对象。
网友评论