如果你不甘心CRUD,那需要看这篇设计模式!|原创
本文首先聊到很多程序员最大的痛点难以摆脱CRUD,以及为什么要学习设计模式,然后介绍了三种容易混淆的设计模式:策略、装饰器、代理。最后给出了如何运用在实际生产中的例子。
点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达
为什么要学习设计模式
为什么要说设计模式?
大家第一个想到的就是在求职时,岗位要求基本都有熟悉设计模式。有些人觉得,这不就是面试造火箭,工作拧螺丝吗?
如果你这么想,那就真的错了!
设计模式在工作中的应用非常广泛,只是天天CRUD撸业务的工作麻痹了你自己!
首先在我们学习新技术并且阅读源码时,熟悉设计模式会让我们感觉轻车熟路,否则在跟踪调试时,你根本不知道代码跳来跳去在做什么。
其次,我们在日常工作中其实是会用到设计模式的,而且很多。很多人抱怨我的日常工作就是CRUD,没什么技术含量,非常枯燥,技术难以进步啊,为什么我没有去架构组或者中间件组的机会。那是因为机会是留给有准备的人的。
如果你工作中连设计模式都没有用到,那真的不够格。现在改变还来得及,其实CRUD也可以写得不一样!
比如我们日常的工作就是撸业务,而Java其实是一个面向对象的语言,我们在写的时候却全部都是面向过程的思想,比如实现一个用户注册功能,逻辑一二三四,一个方法一口气搞定,能把不同功能的方法拆出来就自认为做的很不错了。
而事实真的是这样吗?
这样的代码可能做到了逻辑清晰易读,并且有相对良好的编码习惯,但是并不够优雅。面向对象编程中,很重要的一点就是面向接口编程。并且在设计原则中也同样要求了这点:依赖倒置原则,程序设计应该依赖抽象接口,而不应该依赖具体实现。设计模式就是这一思想的具体行动指南,他直接告诉了我们成熟、优雅的代码设计思路。
本文其实是作为一个引子,给大家列举出几个我常用但是特别容易混淆的设计模式:策略模式、装饰器模式和代理模式。希望通过本文能给大家一些启发。
策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
定义
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
应用
我们将创建一个定义活动的 Strategy 接口和实现了 Strategy 接口的实体策略类。Context 是一个使用了某种策略的类。
StrategyPatternDemo,我们的演示类使用 Context 和策略对象来演示 Context 在它所配置或使用的策略改变时的行为变化。
应用实例:1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。3、JAVA AWT 中的 LayoutManager。
优点:1、算法可以自由切换。2、避免使用多重条件判断。3、扩展性良好。
缺点:1、策略类会增多。2、所有策略类都需要对外暴露。
使用场景:1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。2、一个系统需要动态地在几种算法中选择一种。3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
定义
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码:1、Component 类充当抽象角色,不应该具体实现。2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用
我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。
RedShapeDecorator 是实现了 ShapeDecorator 的实体类。
DecoratorPatternDemo 类使用 RedShapeDecorator 来装饰 Shape 对象。
应用实例:1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景:1、扩展一个类的功能。2、动态增加功能,动态撤销。
注意事项:可代替继承。
代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
如何解决:增加中间层。
关键代码:实现与被代理类组合。
应用
我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage 对象加载的内存占用。
ProxyPatternDemo 类使用 ProxyImage 来获取要加载的 Image 对象,并按照需求进行显示。
应用实例:1、Windows 里面的快捷方式。2、猪八戒去找高翠兰结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。3、买火车票不一定在火车站买,也可以去代售点。4、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。5、spring aop。
优点:1、职责清晰。2、高扩展性。3、智能化。
缺点:1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景:1、远程代理。2、虚拟代理。3、Copy-on-Write 代理。4、保护(Protect or Access)代理。5、Cache代理。6、防火墙(Firewall)代理。7、同步化(Synchronization)代理。8、智能引用(Smart Reference)代理。
注意事项:1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制(简单接口继承的写法上基本相同)。
策略模式和装饰器模式、代理模式区别
策略模式:重点在于避免繁琐的ifelse判断,重点在于执行不同的策略,策略的执行类并不需要实现策略接口。比如用户的
装饰器模式:重点在于如果需要扩展子类实现,并且原有功能不删减,不需要以继承的方式写很多子类。并且会实现统一的接口,而策略模式不需要,这样的好处是装饰类和被装饰类可以独立发展,不会相互耦合。
代理模式:装饰器模式为了增强功能,扩展后的对象仍是是对象本身。而代理模式是为了加以控制,偏重因自己无法完成或自己无需关心,需要他人干涉事件流程。装饰,偏重对原对象功能的扩展,
如何实践
最后本文的以电商中的商户注册为例子来应用上述设计模式。
比如我们注册商户,不可能只有一种场景,比如会通过小程序、CRM、甚至后台直接注册商户,对于注册行为我们抽象为一个接口,我们可以分别去实现对应的实现类。
这只是策略模式初步的应用,更进一步,这三种渠道去注册商户都有类似的流程,比如都需要前置校验,都需要保存用户信息,但是前置验证可能每个渠道内容都不一样,但是最终落库保存的地方逻辑都一样,那我们就可以找出不变和变的地方,利用模版模式来实现(可以自行查询)共同的流程,变得地方各自去实现。
再进一步,如果某种渠道注册的门店需要额外的逻辑,比如通知财务系统、通知活动系统,但是这每一部分都有复杂的业务逻辑,比如通知财务时候有一些数据上的前置校验,那我们就可以把这部分功能单独抽象出来,利用装饰者模式去独立发展,无论你的附加功能如何发展,都不会影响用户注册的主要流程。
而代理模式就不说了,不管是 RPC 还是 spring 中我们到处都在用代理,通常编码中不会直接硬编码,框架已经帮我们做好了。
当然,我并不是让大家有了锤子看什么都是钉子,关键是用在合适的地方。当你可以熟练运用一些设计模式,你会发现你的代码变得复用度很高并且逻辑清晰,扩展性也不错,非常易于维护和后续升级。
希望本文可以给大家一些启发,在CRUD写业务的过程中也可以提升自己的编程思维,写代码也可以更愉快。如有讲得不对的地方欢迎指出。
如果觉得对你有帮助,欢迎点赞、标
如果你看不懂KMP算法,那就看一看这篇文章(绝对原创,绝对通俗易懂) KMP算法,俗称"看毛片"算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易.整个 ... 摘要: 很多值得了解的细节. 原文:Vue开发看这篇文章就够了 作者:Random Fundebug经授权转载,版权归原作者所有. 介绍 Vue 中文网 Vue github Vue.js 是一套构建 ... Vue -渐进式JavaScript框架 介绍 vue 中文网 vue github Vue.js 是一套构建用户界面(UI)的渐进式JavaScript框架 库和框架的区别 我们所说的前端框架与库的 ... 长文,相当的通透.以下为scrat进行总结后的删减版. 下面假定你已经知道时间复杂度 关系型数据库无处不在,而且种类繁多,从小巧实用的 SQLite 到强大的 Teradata .但很少有文章讲解数据 ... 2019独角兽企业重金招聘Python工程师标准>>> 摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所 ... 2019独角兽企业重金招聘Python工程师标准>>> 在刚结束不久的谷歌 I/O2017开发者大会上发布的第二个Android O(安卓8.0)开发者预览,并且向普通用户开放了第二 ... 大家好,我是小浩.今天是小浩算法 "365刷题计划" 滑动窗口系列 - 整合篇.之前给大家讲解过一些滑动窗口的题目,但未作系统整理. 所以我就出了这个整合合集,整合工作中除了保留原 ... 写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ... 本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...如果你不甘心CRUD,那需要看这篇设计模式!|原创相关推荐
最新文章
热门文章