建造者模式
什么是建造者模式
解决了什么问题
使用场景
常见的实现场景
场景案例
使用流行的建造者模式解决问题
不适用建造者模式解决问题
使用传统的建造者模式解决问题
什么是建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
解决了什么问题该模式解决的是如何将一个复杂对象(属性多)赋值的问题
使用场景大家想想,平时如何一个对象赋值?
1、构造器
平时常用的方式,虽然构造器用起来很方便,但随着属性增多,那么需要写的构造器也会增多多,而且容易传混
2、set方式
缺点:对象状态易发生变化,也是一长串,实现起来不美观
常用的实现场景①lombok中的@Builder注解
比如刚才House对象
123456@Builderpublic class House { private String base; private String wall; private String cell;}
在编译后(与我们手动实现的相似)
12345678910111213141516171819202 ...
享元模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
为什么要用享元模式
内部状态与外部状态
应用场景
场景举例
总结
为什么要用享元模式有大量对象可复用,在服务端减少接口的调用,在客户端减少内存的占用
内部状态与外部状态了解享元模式就避不开内部状态与外部状态
内部状态:不随环境的变化而变化,在各个对象间共享
外部状态:随环境的改变而改变,由客户端传入
举例说明,在五子棋中,棋子的颜色就是内部状态,只有黑白两色,落子位置(坐标)是外部状态,每次位置都不一样
如果每一个棋子都是一个对象的话,一个棋盘可以放两三百个对象,极大的浪费内存空间,但如果使用享元模式,则可以很好的解决对象的开销问题
应用场景数据库连接池,String常量池,缓冲池
比如在Integer的源码中有
12345678910static final Integer cache[]; //定义常量数组static{ //....省略,cache的范围在-128~127之间 cache = new Integer[(high - low) + 1];& ...
工厂模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
引子
使用场景
常见应用场景
场景案例
常规思路
简单工厂模式
工厂方法模式
抽象工厂模式
引子相信大家也经常在spring中见到xxxFactoty的字样,工厂模式也算是一个比较常用的设计模式,很有必要掌握
工厂模式分为三种,简单工厂,工厂方法,抽象工厂。其中简单工厂不属于23种设计模式
使用场景不想直接new对象,如果类改变,需要改代码,如果依赖该类的很多,那将是很痛苦的事情
常见应用场景spring中的工厂模式的继承图,之后文章中分析
场景案例假如要生产电脑,比如华为,苹果电脑,如何实现业务?
常规思路定义属性,创建方法,调用展示。
伪代码,一个类就可以实现,给我A创建A电脑,给B创建B电脑
12345if("A".equlas(type)) { //生产A电脑} else if("B".equlas(type)) { //生产B电脑}
假设在添加一个C电脑
1234567if(& ...
代理模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
日常生活中常见的代理比如说老板秘书,明星经纪人,本来是老板或明星的活,代理就都给干了,除此之外,还可能多做一些额外的,比如帮明星筹建演唱会,打官司,做公关之类的
为什么需要代理模式
代理模式种类
应用场景
静态代理
动态代理
cglib代理
总结
为什么需要代理模式1、客户端可能无法直接操作对象(在另一台机器),那么可以在客户端建立一个代理对象,然后客户端直接调用目标对象,代理对象在与目标对象建立联系
2、需要加强目标对象的功能。有人表示为什么不在当初的类中加好,要使用代理来补充。单一职责要求一个类的功能尽可能单一,而且增强的功能大多都是与之前业务不同,比如增加日志输出,权限判断等,本来就不应该由之前的类去承担
种类静态代理,动态代理(jdk代理/接口代理),cglib代理
在《精通Spring4.x 企业应用开发实战》给出建议
单例使用cglib,多例使用jdk
原因:jdk创建对象性能高于cglib,而生成对象的运行性能却比cglib低
应用场景最常见的就是spring的AOP ...
外观模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
通用类图
场景举例
优点
缺点
注意
总结
通用类图
把功能统一到一块,形成一个总控,就类似于家里电闸的总开关,可以控制所有的电器
就拿我们公司举例,如果我平时遇到某个系统的问题,比如财务的问题找财务系统负责人,人力的找人力负责人,我还得知道他们是谁,我也没必要记住他们,那么一个角色出现了,充当了中间人的作用,那就是客服,我知道如果出问题了,就去找她,她给我找具体的人,这就是外观模式的一种体现
角色这样看下来一共有两个角色
外观,相当于客服
子系统,相当于各个部门的负责人
场景举例拿总控进行举例,如果我按总开关打算控制家中所有的灯,那么代码如下
先看调用端
12345678910//外观模式,一步齐活new Facade().open();new Facade().close();//传统方式,挨个调用new BedRoom().open();new Kitchen().open();new LivingRoom().open();new BedRoom().close();new ...
桥接模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
这是一个不常用的设计模式,了解核心思想即可
什么是桥接模式
应用场景
场景举例
Java实现
什么是桥接模式1、将抽象部分与实体部分分离
2、处理多个独立变化的维度,在抽象层建立关联,其中抽象类作为桥
3、通过构造函数的方式将接口传入实现联系
应用场景JDBC多种驱动的实现
场景举例目前有支付方式wx支付与zfb支付,有解锁方式人脸识别与指纹解锁
现需要两种方式结合的方式才能完成付款功能,如何进行实现?
如果采用传统的方式,可得到类图
此时如果加一个云闪付,那么需要增加3个类,增加一个密码解锁需要增加2个类
这个只是最简单的举例,实际业务远比这复杂得多,可以想象到,如果进行扩展,就很容易出现类爆炸的情况,这个时候使用桥接模式,可以很好的应对这种情况
传统方式的源码可以去git查看,这里就不贴了
桥接模式的类图
可以看到解锁抽象类当作桥,用于连接支付接口,扩展十分方便
Java实现支付接口
123public interface IPay { void pay ...
组合模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
定义
角色
类图
种类
场景举例
实际应用场景
总结
定义组合模式定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。
角色Component(抽象构件):声明公共行为
Leaf(叶子结点,树叶构件):没有子节点
Composite(树枝构件):存储或管理子部件,有独特的list
通用类图
以其他形式展现在文件系统中可改写为如图,文件为抽象类定义了对象的一些属性及方法,具体的由文件夹和文件去实现,而文件只实现操作方法(getName)
而在别的场景中,如组织结构,这个文件夹就相当于一个统称了,比如一级部门下有二级,二级下有三级,等等,那么最后一级部门作为叶子节点,其余部门就全部充当树枝节点了
种类组合模式有透明方式与安全方式
透明方式表示用户使用的时候不管 ...
适配器模式
设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
什么是适配器模式
有几种适配器种类(了解)
应用场景
应用场景简单实现
什么是适配器模式如图,将4个口最终转为一个口的能力,实现了很好的兼容
在程序对应中,将多个对象类型转为一个对象类型去调用方法
有几种适配器种类(了解)类适配器适配器类需要继承被适配器类(原来的东西)实现目标接口(转换得到的东西)
缺点:继承耦合性强,暴露了被适配器中的方法,好处是可以重写
对象适配器不在继承,而是new一个实例,系统中尽量不使用继承关系,所以对象适配器是常用的一种
接口适配器有些适配方法不需要全部实现,这种情况下可以使用一个抽象类实现接口中的全部方法,然后用匿名内部类的方式实现自己用的方法。类似于监听器类
应用场景springmvc中的DispatcherServlet类中doDispatch方法中很清楚的出现了适配器的影子,只要把这块为什么作者使用适配器搞懂了,这个模式也就理解大半了,剩下的就是不断实践
1、首先根据传入的request来获取对应的handler
2、利用获取的handl ...