@TOC
需要有一定设计模式基础的看,可以结合菜鸟教程等等的来一起看
1.1 工厂方法模式
将多段代码的共性行为抽象到接口中去定义,具体的实现由子类实现父类后去定义。最后,通过一个工厂类去根据传参来选择返回对应的实例化对象。
关键词:工厂类一般带有Factory
1.2 抽象工厂模式
抽象工厂的本质是其它工厂类的抽象类,也就是将其他工厂类中的共性行为提取到了抽象工厂类
AbstractXXX
小傅哥在抽象工厂模式中是使用了抽象工厂的另一种实现,其中用到了代理、适配器、抽象工厂几个点,这里为CacheService的两种缓存模式实现加上了适配器,使其对应的方法与CacheService接口的方法对应,然后使用了动态代理,在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。
可以将不同的缓存模式的适配器类看作为工厂的构建类,这些工厂类都存在有共性的getter、setter。
这些共性行为被抽象到了CacheService中,通过动态代理,在service调用的方法实际上调用的是适配器类中的方法。
CacheService proxy_EGM = JDKProxy.getProxy(CacheServiceImpl.class, new EGMCacheAdapter());
proxy_EGM.set("user_name_01", "小傅哥");
String val01 = proxy_EGM.get("user_name_01");
System.out.println("测试结果:" + val01);
CacheService proxy_IIR = JDKProxy.getProxy(CacheServiceImpl.class, new IIRCacheAdapter());
proxy_IIR.set("user_name_01", "小傅哥");
String val02 = proxy_IIR.get("user_name_01");
System.out.println("测试结果:" + val02);
1.3 建造者模式
日常生活中,装修房子会根据不同的场景、品牌、型号、价格等等组合形成了各式各样的装修风格(套餐A:现代简约,套餐B:轻奢田园,套餐C:欧式豪华)
一些基本物料不会变,而其组合经常变化的时候,就可以选择这样的构建者模式来构建代码。Builder
1.4 原型模式
在考试中,每个考生得到的考卷题目大致相同,都是从同一个考题池中随机组合一套题目出来分发给所有考生进行考试,但是这样得到的题目,题序一样,容易引起作弊,而且还是不断地创建初始化统一对象。
使用原型模式:通过克隆方式创建复杂对象、也可以避免重复做初始化操作、不需要与类中所属的其他类耦合等。但也有一些缺点如果对象中包括了循环引用的克隆,以及类中深度使用对象的克隆,都会使此模式变得异常麻烦。(在重写的克隆方法中进行乱序)
实现了Cloneable
1.5 单例模式
每次拿到或者创建获得的都是同一个实例
例如:Spring中的通过@Autowird自动注入获取的对象也是单例模式的一种体现(设定的Bean注入模式是单例),其底层是通过Bean的注入模式去决定,单例模式是将new创建的实例放入容器,每次拿到的都是这个实例对象,原型模式的话就是把创建类的Class对象放入容器,每次拿都是调用这个Class.newInstance
推荐使用枚举单例模式
这种方式解决了最主要的;线程安全、自由串行化、单一实例。
enum
1.6 适配器模式
为存在共性行为但是调用方法不同的类创建适配器接口,适配器的实现类实际上调用的是原对象的对应方法。
接口已经做了统一的包装,外部使用时候就不需要关心内部的具体逻辑了。而且在调用的时候只需要传入统一的参数即可,这样就满足了适配的作用。
Adapter
1.7 桥接模式
桥接模式的主要作用就是通过将抽象部分与实现部分分离,把多种可匹配的使用进行组合。说白了核心实现也就是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥。
通过模拟微信与支付宝两个支付渠道在不同的支付模式下,刷脸、指纹、密码,的组合从而体现了桥接模式的在这类场景中的合理运用。
在支付方式中桥接了指纹支付、人脸支付
Pay zfbPay = new ZfbPay(new PayFingerprintMode());
Bridge/在初始化时传入其它对象作为本类执行方法的判断
1.8 组合模式(没细品)
组合模式的主要解决的是一系列简单逻辑节点或者扩展的复杂逻辑节点在不同结构的组织下,对于外部的调用是仍然可以非常简单的。
1.9 装饰器模式(没细品)
new BufferedReader(new FileReader(""));,这段代码你是否熟悉,相信学习java开发到字节流、字符流、文件流的内容时都见到了这样的代码,一层嵌套一层,一层嵌套一层,字节流转字符流等等,而这样方式的使用就是装饰器模式的一种体现。
1.10 外观模式(没细品)
外观模式也叫门面模式,主要解决的是降低调用方的使用接口的复杂逻辑组合。这样调用方与实际的接口提供方提供方提供了一个中间层,用于包装逻辑提供API接口。有些时候外观模式也被用在中间件层,对服务中的通用性复杂逻辑进行中间件层包装,让使用方可以只关心业务开发。
1.11 享元模式
享元模式,主要在于共享通用对象,减少内存的使用,提升系统的访问效率。而这部分共享对象通常比较耗费内存或者需要查询大量接口或者使用数据库资源,因此统一抽离作为共享对象使用。
通过各种方式将可重用的数据进行缓存整个对象,减少内存占用和查询次数
在活动秒杀的场景之下,活动的信息是不不变的,只有商品的库存在发生变换,每次从数据库种获取到的活动信息对象除了库存信息其它都是一致的,这个时候可以使用享元模式,将重复的部分缓存起来重复使用,这里使用了项元工厂,用map在初始化时从数据库缓存活动信息,库存信息由之后从redis种获取后拼接到活动信息中。
1.12 代理模式(没有细品)
代理模式有点像老大和小弟,也有点像分销商。主要解决的是问题是为某些资源的访问、对象的类的易用操作上提供方便使用的代理服务。而这种设计思想的模式经常会出现在我们的系统中,或者你用到过的组件中,它们都提供给你一种非常简单易用的方式控制原本你需要编写很多代码的进行使用的服务类。
大概就是:实现了代理之后的一些列封装设计。
代理模式的讲解我们采用了开发一个关于mybatis-spring中间件中部分核心功能来体现代理模式的强大之处,所以涉及到了一些关于代理类的创建以及spring中bean的注册这些知识点,可能在平常的业务开发中都是很少用到的,但是在中间件开发中确实非常常见的操作。
代理模式除了开发中间件外还可以是对服务的包装,物联网组件等等,让复杂的各项服务变为轻量级调用、缓存使用。你可以理解为你家里的电灯开关,我们不能操作220v电线的人肉连接,但是可以使用开关,避免触电。
代理模式的设计方式可以让代码更加整洁、干净易于维护,虽然在这部分开发中额外增加了很多类也包括了自己处理bean的注册等,但是这样的中间件复用性极高也更加智能,可以非常方便的扩展到各个服务应用中。
1.13 责任链
这个我熟,比较常用也比较简单的一种,责任链模式的核心是解决一组服务中的先后执行处理关系,就有点像你没钱花了,需要家庭财务支出审批,10块钱以下找闺女审批,100块钱先闺女审批在媳妇审批。你可以理解想象成当你要跳槽的时候被安排的明明白白的被各个领导签字放行。
责任链模式
1.核心思想
链式有序执行,每一节点的执行都依赖于上一级节点的执行结果。
2.结构划分
抽象父类:Action
属性:Action action
用于存放指向下一结点的对象引用
抽象方法:start()
由实现的子类去定义当前节点具体的逻辑实现
方法:action()
结点执行判断分支,成功-进入下一节点的do执行,失败-执行完毕返回
子类:openDeviceAction(等等多个子类节点)
重写start()方法实现具体的逻辑
组装执行类:Call(封装好执行行为顺序、逻辑,哪里需要哪里用)
创建需要用到的节点,用setNext指定下一节点(执行顺序),调用第一个节点的action()启动
3.特点、关键词
链表数据结构,责任链的本质就是一种链表数据结构,通过节点指向下一节点来确保节点的执行顺序,(Next、Node)
1.14 命令模式
命令场景的核心的逻辑是调用方与不需要去关心具体的逻辑实现,在这个场景中也就是点餐人员只需要把需要点的各种菜系交个小二就可以,小二再把各项菜品交给各个厨师进行烹饪。也就是点餐人员不需要跟各个厨师交流,只需要在统一的环境里下达命令就可以。
其实我的理解就是这种模式就是一种行为的封装,下次想要用到这部分的代码就直接调方法,而不是写一长串的一条条代码。
这里的特点就是被调用方及行为被抽象到接口中了,在调用方可以利用多态调用用过被调用方的具体实现及行为方法
命令模式的使用场景需要分为三个比较大的块;命令、实现、调用者,而这三块内容的拆分也是选择适合场景的关键因素,经过这样的拆分可以让逻辑具备单一职责的性质,便于扩展。
1.15 迭代器模式(没有细品)
迭代器模式,常见的就是我们日常使用的iterator遍历。虽然这个设计模式在我们的实际业务开发中的场景并不多,但却几乎每天都要使用jdk为我们提供的list集合遍历。另外增强的for循环虽然是循环输出数据,但是他不是迭代器模式。迭代器模式的特点是实现Iterable接口,通过next的方式获取集合元素,同时具备对元素的删除等操作。而增强的for循环是不可以的。另外,迭代过程中是不允许删除元素的。
这种设计模式的优点是可以让我们以相同的方式,遍历不同的数据结构元素,这些数据结构包括;数组、链表、树等,而用户在使用遍历的时候并不需要去关心每一种数据结构的遍历处理逻辑,从让使用变得统一易用。
1.16 中介者模式(没有细品)
中介者模式要解决的就是复杂功能应用之间的重复调用,在这中间添加一层中介者包装服务,对外提供简单、通用、易扩展的服务能力。
这样的设计模式几乎在我们日常生活和实际业务开发中都会见到,例如;飞机降落有小姐姐在塔台喊话、无论哪个方向来的候车都从站台上下、公司的系统中有一个中台专门为你包装所有接口和提供统一的服务等等,这些都运用了中介者模式。除此之外,你用到的一些中间件,他们包装了底层多种数据库的差异化,提供非常简单的方式进行使用。
个人理解就是为了解决复杂场景下的资源顺序调度问题。
1.17 备忘录模式(没有细品)
备忘录模式是以可以恢复或者说回滚,配置、版本、悔棋为核心功能的设计模式,而这种设计模式属于行为模式。在功能实现上是以不破坏原对象为基础增加备忘录操作类,记录原对象的行为从而实现备忘录模式。
个人理解就是在执行一段信息修改的同时,先将上一条消息通过缓存、存表之类的先记录起来,之后通过历史记录进行回滚到需要的配置信息。
1.18 观察者模式
简单来讲观察者模式,就是当一个行为发生时传递信息给另外一个用户接收做出相应的处理,两者之间没有直接的耦合关联。
例如;狙击手、李云龙。以及许多框架中都会有的监听器,通过注解的方式,当监听的方式执行后,也会执行对应的监听方法(监听数据库库存发生变化,前端统计商品库存等也要发生改变)。还有MQ中的消费者模式,也是通过监听队列中的消息,然后再去消费,这也是一种观察者模式的思想,监听行为、订阅
1.19 状态模式
状态模式描述的是一个行为下的多种状态变更,比如我们最常见的一个网站的页面,在你登录与不登录下展示的内容是略有差异的(不登录不能展示个人信息),而这种登录与不登录就是我们通过改变状态,而让整个行为发生了变化。
至少80后、90后的小伙伴基本都用过磁带放音机,它的上面是一排按钮,当放入磁带后,通过上面的按钮就可以让放音机播放磁带上的内容(listen to 英语听力考试),而且有些按钮是互斥的,当在某个状态下才可以按另外的按钮(这在设计模式里也是一个关键的点)。
不同状态下而展示的不同页面、能查询到的不同的数据,如果区级单位只看当前区,市级单位可以看所有区,根据状态、单位、某一个字段的不同以此逐级控制。
1.20 策略模式
策略模式也是用的最多也是最简单的一种设计模式了,常常用于替换多分支ifelse的抉择场景,前提改业务流程拥有不定未来扩展趋势,否则不符合使用场景。
如:当前系统需要做一个接入第三方支付的一个功能,这里可以使用策略者模式去创建不同支付方式分支的具体实现,就算暂时支持了:微信、支付宝、钱包等支付方式,但是随着业务量的发展和用户群体的激增,无法避免之后需要扩展加入支持银联支付等等的场景,这种时候使用策略模式较为合理。最后,策略模式的实现是通过在接口中去抽象多分支的行为方法,具体的实现由子类去定义。策略模式还需要一个策略控制类根据传入的对象利用多态去调用具体的实现。
ifelse-->策略接口、实现类、策略控制类(重点:切记当前业务是有扩展性的才去选择使用,要不然如果只是写死内容的两三个分支也去使用策略模式反而增加了内存消耗与管理成本)
1.21 模板模式(没有细品)
模板模式的核心设计思路是通过在,抽象类中定义抽象方法的执行顺序,并将抽象方法设定为只有子类实现,但不设计独立访问的方法。简单说也就是把你安排的明明白白的。
模版模式在定义统一结构也就是执行标准上非常方便,也就很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体的业务逻辑实现即可。
1.22 访问者模式(没有细品)
访问者要解决的核心事项是,在一个稳定的数据结构下,例如用户信息、雇员信息等,增加易变的业务访问逻辑。为了增强扩展性,将这两部分的业务解耦的一种设计模式。
1.23 解释器模式
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
有点类似于代码生成器中, 用实际查询到的数据 "张三" 解释替换了 {name}表达式。
二、参考:
小傅哥:https://bugstack.cn/itstack/i...
欢迎转载,请注明出处。
三、更新日志
9-7
- 初略贴出二十三种设计模式核心概念,后续完善补充
我是林熙,非常感谢大家的支持!一起学习,一起进步!