一下模式都在本人博客中有对应的教程,自己搜索
无论承接什么样的需求,是不是身边总有那么几个人代码写的烂,但是却时常有测试小姐姐过来聊天(求改bug)、有产品小伙伴送吃的(求写需求)、有业务小妹妹陪着改代码(求上线),直至领导都认为他的工作很重要,而在旁边的你只能蹭点吃的。
那你说,CRUD的代码还想让我怎么样?
这样的小伙伴,可能把代码写的很直接,if else
多用一点,满足于先临时支持一下,想着这也没什么的。而且这样的业务需求要的急又都是增删改查的内容,实在不想做设计。而如果有人提到说好好设计下,可能也会被反对不要过渡设计。
贴膏药似的修修补补,一次比一次恐怖!
第一次完成产品需求实在是很快,但互联网的代码不比传统企业。在传统行业可能一套代码能用十年,但在互联网高速的迭代下你的工程,一年就要变动几十次。如果从一开始就想着只要完成功能就可以,那么随之而来的是后续的需求难以承接,每次看着成片成片的代码,实在不知如何下手。
在研发流程规范下执行,才能写出好程序!
一个项目的上线往往要经历业务需求、产品设计、研发实现、测试验证、上线部署到正式开量,而这其中对研发非常重要的一环就是研发实现的过程,又可以包括为;架构选型、功能设计、设计评审、代码实现、代码评审、单测覆盖率检查、编写文档、提交测试。所以在一些流程规范下,其实很难让你随意开发代码。开发代码的过程不是炫技,就像盖房子如果不按照图纸来修建,回首就在山墙上搭一个厨房卫浴!可能在现实场景中这很荒唐,但在功能开发中却总有这样的代码。
所以我们也需要一些设计模式的标准思想,去建设代码结构,提升全局把控能力。
设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。
这 23 种设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解。
当然,软件设计模式只是一个引导,在实际的软件开发中,必须根据具体的需求来选择:
设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式的六大原则
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
以下模式都能在我博客里找到对应的实现,和详情解析
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
单例模式(Singleton),也叫单子模式,是一种常用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候,整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,显然,这种方式简化了在复杂环境下的配置管理。
特别,在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。事实上,这些应用都或多或少具有资源管理器的功能。例如,每台计算机可以有若干个打印机,但只能有一个 Printer Spooler//(单例)// ,以避免两个打印作业同时输出到打印机中。再比如,每台计算机可以有若干通信端口,系统应当集中 //(单例)/*/*管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态
综上所述,单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。
定义:工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,而不必事先知道每次要实例化哪一个类。
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作子类去做,这个核心类则成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
适用场景:
优点:
缺点:
抽象工厂模式:提供一个创建一系列或相互依赖的对象的接口,而无需指定它们的具体类。
适用场景:
优点:
缺点:
建造者模式又被称呼为生成器模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
使用多个简单的对象一步一步构建成一个复杂的对象,
建造者模式所完成的内容就是通过将多个简单对象通过一步步的组装构建出一个复杂对象的过程。
例如你玩王者荣耀的时的初始化界面;有三条路、有树木、有野怪、有守卫塔等等,甚至依赖于你的网络情况会控制清晰度。而当你换一个场景进行其他不同模式的选择时,同样会建设道路、树木、野怪等等,但是他们的摆放和大小都有不同。这里就可以用到建造者模式来初始化游戏元素。
而这样的根据相同的物料,不同的组装所产生出的具体的内容,就是建造者模式的最终意图,也就是;将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
原型模式: 通过给出一个原型对象来指明所创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
将一个类的接口转成客户期望的另外一个接口。适配器模式使得原本由于接口不匹配而不能一起工作的那些类可以一起工作。
如图所示,这有一个适配器,一号口是typec口,二号口是vga口,只有将视频信号从typec口输入,转换输出到vga口,才能和投影仪对接,实现手机屏幕投影到投影仪上的任务。
装饰器模式其实比较常见,大家在开发过程中其实经常用到,只不过自己还没发觉自己用到了装饰器这种设计模式,下面通过一个生活中的例子来介绍装饰器模式。
那煎饼果子来说,我们知道煎饼果子有各种配置,加鸡蛋加香肠加生菜加肉等各种豪华配置(BGM:哟哟,切克闹,煎饼果子来一套,我说鸡蛋你说要)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需修改,可以通过代理的方式来扩展该方法
举个例子来说明代理的作用:
假设我们想邀请一位明星,那么并不是直接联想明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子
外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,使子系统与客户端的耦合度降低,且客户端调用变得更加方便。简而言之,就是说外观模式是用来简化调用操作的!
外观模式:为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶的话,需要准备茶叶,茶具,和开水。而去茶馆的话就只需要说老子要一碗冰红茶就OK了,服务员会帮你准备好一切。泡茶的过程我们就不用考虑了。贼方便。
所以在软件过程中为了完成一项比较复杂的功能的时候,一个客户类需要和多个业务类进行交互,而这些需要交互的业务类,也通常以一个整体出现,由于涉及的类比较多,导致使用时代码较为复杂,此时特别需要向茶馆服务员这样的关键人物出现,让他来帮我泡茶岂不美滋滋?。
外观模式就是干这活,用来简化客户端和其他 各种各样的业务接口打交道的麻烦。
我们都去买过手机,手机按照品牌分可以分为华为、小米、oppo、vivo等品牌,如果这些手机按照内存分又可以分为4G、6G、8G等等。假如我们每一种手机都想要玩一下,至少需要4/*3个。这对我们来说这些手机也太多了,竟然有12个,最主要的是手机品牌和内存是放在一起的。现在有这样一种机制,手机牌品商是一个公司,做手机内存的是一个公司,想要做什么手机我们只需要让其两者搭配起来即可。有点类似于全球贸易分工明确的思想,这就是桥接模式,把两个不同维度的东西桥接起来。
组合模式定义为,允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及组合对象。
组合模式,能够让我们用树形方式创建对象的结构,树里面包含了组合以及个别对象。我们可以把相同的操作应用到组合对象和个别对象中。在这种模式中,组合对象是可以包含个别对象的,而个别对象就是树形结构中的叶子节点。
一般利用组合模式,组合对象和个别对象均要实现同样的接口。组合模式应用场景主要是在当有多个对象的时候,他们彼此之间有“整体/部分”的关系,并且想要给客户一种一致的方法来对待这些对象的时候,就需要这种模式。组合模式能够使的客户不再担心面对的是组合对象或者个别对象,他们只需要对整个结构调用一个方法就可以了
就是将需要的对象组合到一起 客户以一致的方式处理个别对象
一个系统中若存在大量相同或相似的对象(比如26个英文字母),则只共享一份就可以了(并非单例模式),没有必要为每份相同的东西还都单独实例化出一个对象,浪费性能。(有点缓存的意思)
比如26个英文字母,一个文本中有10MB的26个英文字母,那你解析出来的时候需要为每一个字母都创建一个对象的话(10M那么大,对象数不可直视。。。),内存肯定扛不住。所以可以用享元模式,只创建26个对象进行共享就行了。
还有就是: 当一个系统中出现了大量相同或者相似的细粒度对象的时候。细粒度就是小对象,属性少方法少的对象。就可以可以考虑使用享元模式来就行系统的设计
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
在现实生活中,我们应该很熟知的一句话,“红灯停,绿灯行,黄灯亮了等一等”。很多人会问,这和我们今天聊的主题有什么关系呢,
正文来了,我们现在来聊一下,我们刚刚说过的“红灯停,绿灯行,黄灯亮了等一等”,我们正常的时候,遇到这种问题,我们一般会用if…else来解决这列问题,或者使用swith来解决这种条件的问题。接下来我们看看这部分代码的实现。
//交通灯
if(light.equals("red")){
System.out.println("红灯停");
}else if(light.equals("yellow")){
System.out.println("黄灯亮了等一等");
}else if(light.equals("green")){
System.out.println("绿灯行");
}
switch (light){
//红灯
case 0:
System.out.println("红灯停");
break;
//黄灯
case 1:
System.out.println("黄灯亮了等一等");
break;
//绿灯
case 2:
System.out.println("绿灯行");
break;
}
这两种方案都可以实现我们的“红灯停,绿灯行,黄灯亮了等一等”的方案。但是这样会导致我们的代码和逻辑比较复杂,维护起来很浪费人力物力。接下来我们的主角(策略模式)就要出场了。那么咱们的主角比起前两种,会有哪些个优势呢。“策略模式”把这些算法,都抽取出来,组成一个一个的类,可以任意的替换,大大降低了代码的耦合度。
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通俗的说的就是有很多相同的步骤的,在某一些地方可能有一些差别适合于这种模式,例如想要泡一杯茶或者一杯咖啡,第一步都是将水煮沸,第二部是加入咖啡或者茶,第三部就是将饮料倒入杯子中,第四部就是加入各种调味料。其中第一步和第三部都是一样的,这个就可以定义在基类,而第二步和第四步就是他们之间的差异就可以在具体的子类中去实现。
简单来说:一些方法通用,却在每一个子类都重新写了这一方法,带来大量重复的代码的问题。相同的部分父类给出统一的模板,不同的部分,子类进行重写。
观察者模式:是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
观察者模式就相当于java里面的一对多的关系,多的一方称之为观察者,可以是一,也可以是多,一的一方也被称为被观察者,用现实中的某样事物来比喻的话,个人觉得更像是报纸,被观察者就相当于报纸公司,它在报纸中发布各种信息,然后每一名读者,也就是购买报纸的人,就会收到这条信息。
验钞机相信大家都见过吧,也就是能够快速的将一大捆钱翻检然后看是否存在假钞,如果发现假钞则停下来将它取出来。这种能够将一个聚合体,容器里面的所有对象或物品迭代搜索或者迭代取出来的模式就是迭代模式,这种模式在程序语言中经常能够接触到,并且非常实用,只不过都已经封装好了不需要我们对它进行重写。
比如 List set …
将多个对象通过引用连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。对于客户来说并不知道请求在哪一个环节被处理了。从而实现了请求和处理之间的解耦合。
这条链其实有很多种,比如说就是一条直直的链,或者是一条环形链,再或者是一颗树。
责任链模式很容易理解,比如说古代的时候,前方战线的信息的传递,首先是前线将军将战况交给通信兵,接下来通信兵不能为当前的状况作出指令,于是乎跑到了京城把信息交给了大臣,大臣也不能做决定,于是又把信息交给了皇帝。最终皇帝处理当前的战况信息。这就是责任链模式。整个的处理过程就像是一条链一样。
简单来说就是将 需要的功能 都封装到 一起 通过一条代码来执行 就好比Linux的命令
比如: 插座上关联的有 电视 灯 空调 当我开启插座电源开关 的时候 那么这些电器就能正常工作了
当我关闭插座电源开关 的时候这些 电器就不能正常工作
注意: 我们从始至终 就只有 开和关 这两个操作 就能控制其他电器 的运行情况 这就是命令模式 将所有相关操作都封装到一个操作里 通过调用这个操作 从而调用内部的多个操作
都说人生没有后悔药可买,我们都在为所做的事付出着代价,但在软世界里却有“后悔药”,我改变了某东西的某些状态之后,只要我们之前保存了该东西的某状态,我们就可以通过备忘录模式实现该东西的状态还原,其实这何尝不是一个能使时光倒流的“月光宝盒”,
在比如 : 你炒股 后发现 股票大跌 那么就可以通过 被备忘录模式来还原到之前没买股票稍微状态
通过对象内部状态发生改变进而来改变对象的行为,对象看起来好像是被修改了一样。
如,没有糖果的时候(是一个状态),糖果机就不能运行了,有糖果之后(另一个状态),投币就可以出糖果了。
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下,定义作用于这些元素的新操作。
如何来理解呢?举个例子来说吧,假如我们都玩过王者荣耀。每个英雄都有三个基本的技能,但是不同的玩家操作英雄技能实现的方式是不一样的。比如说你玩韩信只能送人头,梦泪玩韩信那就是百战百胜。
可以理解为英雄是固定的 但是操作 因人而异 最后产生的效果也不同
简单的来说就是提供一个平台。比如生活中我们经常用到的聊天软件QQ、微信群,或者是上网购物的网站淘宝、京东,又或者是房产中介。但是无论是QQ群,还是房产中介,他们都是充当一个中间平台的作用,我们可以直接通过这个平台得到我们想要的信息,避免了独自获取花费的成本。
这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
比如 正则表达式解析器 我们只需要按照正则表达式解析器的规则来写 那么正则表达式解析器 就能解析
在简单来说 :我们自定义一个解析器 用于解析 true 和fasle 翻译成中文
如果你传入为true 那么返回给你一个正确 如果你传入 false 就给你返回一个错误
有时候我们的代码中为避免 NullPointerException 会出现很多的对Null的判断语句,而这些语句一旦多起来,我们的代码就会变的惨不忍睹,因此我们引入了空对象模式(null object pattern)以此来使我们的代码变的更优雅一点。
简单来说就是 定义过滤要求 过滤掉不符合要求的对象
MVC是Model-View-Controller的简称,即模型-视图-控制器。MVC是一种设计模式,它把应用程序分成三个核心模块:模型,视图,控制器,它们各自处理自己的任务。
模型(体现在下图中的POJO和数据库)是应用程序的主体部分,表示业务数据和业务逻辑。一个模型能为多个视图提供数据。由于应用于模型的代码只需要写一次就可以被多个视图重用,所以提高了代码的可重用性。
*
视图是用户看到并与之交互的界面,可以向用户显示相关的数据,也可以接收用户的输入,但是不进行任何实际的业务处理。
*
控制器接收请求,获取请求参数,调用DAO方法,决定用哪个模型组件去处理请求,然后决定调用哪个视图来显示模型处理返回的数据。
业务代表模式(Business Delegate Pattern)用于对表示层和业务层解耦。它基本上是用来减少通信或对表示层代码中的业务层代码的远程查询功能。在业务层中我们有以下实体。
组合实体模式(Composite Entity Pattern)用在 EJB 持久化机制中。一个组合实体是一个 EJB 实体 bean,代表了对象的图解。当更新一个组合实体时,内部依赖对象 beans 会自动更新,因为它们是由 EJB 实体 bean 管理的。以下是组合实体 bean 的参与者。
数据访问对象模式(Data Access Object Pattern)或 DAO 模式用于把低级的数据访问 API 或操作从高级的业务服务中分离出来。以下是数据访问对象模式的参与者。
数据访问对象接口(Data Access Object Interface) - 该接口定义了在一个模型对象上要执行的标准操作。
数据访问对象实体类(Data Access Object concrete class) - 该类实现了上述的接口。该类负责从数据源获取数据,数据源可以是数据库,也可以是 xml,或者是其他的存储机制。
模型对象/数值对象(Model Object/Value Object) - 该对象是简单的 POJO,包含了 get/set 方法来存储通过使用 DAO 类检索到的数据。
前端控制器设计模式用于提供集中式请求处理机制,以便所有请求将由单个处理程序处理。此处理程序可以执行请求的身份验证/授权/记录或跟踪,然后将请求传递到相应的处理程序。 以下是这种类型的设计模式的实体。
拦截过滤器模式(Intercepting Filter Pattern)用于对应用程序的请求或响应做一些预处理/后处理。定义过滤器,并在把请求传给实际目标应用程序之前应用在请求上。过滤器可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。以下是这种设计模式的实体。
当我们想要使用JNDI查找来定位各种服务时,使用服务定位器设计模式。 考虑到为服务查找JNDI的高成本,所以在服务定位器模式使用缓存技术。 首次需要服务时,服务定位器在JNDI中查找并缓存服务对象。 通过服务定位器进一步查找或相同的服务在其缓存中完成,这在很大程度上提高了应用的性能
当我们想要在客户端到服务器的一个传递具有多个属性的数据时,可使用传输对象模式。传输对象也称为值对象。传输对象是一个具有getter/setter方法的简单POJO类,并且是可序列化的,因此可以通过网络传输。 它没有任何行为。服务器端业务类通常从数据库获取数据并填充到POJO类,并将其发送到客户端或通过值传递它。对于客户端,传输对象是只读的。 客户端可以创建自己的传输对象,并将其传递给服务器,以便一次性更新数据库中的值。 以下是这种类型的设计模式的实体。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_45203607/article/details/120238604
内容来源于网络,如有侵权,请联系作者删除!