0305 - 设计模式
2021-05-12 23:03:21 0 举报
AI智能生成
系统架构、Java技术栈、面试宝典
作者其他创作
大纲/内容
单例模式
饿汉方式
懒汉方式
双重检测机制
单例注册表方式
工程模式
应用场景
Spring创建Bean
代理模式
应用场景
Motan服务的动态代理
分类
静态代理
编译的时就已经创建好了代理类
动态代理
JDK动态代理
CGLIB
Javassist
构造者模式
应用场景
PB序列化中的Builder
责任链模式
应用场景
Netty消息处理的方式
适配器模式
应用场景
SLF4J如何支持Log4j
观察者模式
应用场景
GRPC是如何支持流式的请求
其它模式
设计模式
创建型6种
单例模式(Singleton)
懒汉式
饿汉式
懒汉式(双重检测)
静态内部类
枚举类
工厂模式(Factory)
简单工厂模式
子主题
工厂方法模式
具体工厂生产具体的产品,在简单工厂基础上增加了“抽象工厂”角色
抽象工厂模式
包含创建一族产品的工厂方法,每个方法对应一个产品族
建造者模式(Builder)
原型模式(Prototype)
背景
与其它创建型模式不同,原型模式不是在他们的基础上的改进
概念
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。本质: 通过一个原始对象为模版,克隆出更多一模一样的对象;
在java中就是clone方法;
在java中就是clone方法;
目的
提高效率、绕过构造方法、使用方便
优缺点
优点:
--高性能
通过new进行创建对象时,需要首先获取class信息,计算出所需内存大小,分配内存,赋默认值,执行代码块、执行构造方法初始化 等一系列动作;
而使用clone方法,只需要根据原始对象大小分配内存,然后复制二进制流即可;省去了很多的计算和初始动作;因此性能会较高;
--绕过构造方法
这个即是优点,某些情况下可能也是缺点;
如果一个对象的初始化非常消耗性能,比如:通过加载数据库配置,则绕过构造方法会大大提高性能;
--使用简单
这也是创建型模式的基本优点,它隐藏了对象创建的内部细节;
最核心的目的:高性能、方便、快速的创建出大量一模一样的对象
-----------------------------------------------------------------------------------------------------------------------------------------------------------
缺点:
--绕过构造方法
--一些必须通过构造方法进行不同初始化的操作将无法执行;
--高性能
通过new进行创建对象时,需要首先获取class信息,计算出所需内存大小,分配内存,赋默认值,执行代码块、执行构造方法初始化 等一系列动作;
而使用clone方法,只需要根据原始对象大小分配内存,然后复制二进制流即可;省去了很多的计算和初始动作;因此性能会较高;
--绕过构造方法
这个即是优点,某些情况下可能也是缺点;
如果一个对象的初始化非常消耗性能,比如:通过加载数据库配置,则绕过构造方法会大大提高性能;
--使用简单
这也是创建型模式的基本优点,它隐藏了对象创建的内部细节;
最核心的目的:高性能、方便、快速的创建出大量一模一样的对象
-----------------------------------------------------------------------------------------------------------------------------------------------------------
缺点:
--绕过构造方法
--一些必须通过构造方法进行不同初始化的操作将无法执行;
现时案例
jdk 中的cloneable接口
对象克隆
深克隆
是指复制的两个对象本身及对象的属性(包括所有递归属性)都是完全全新的对象;在内存是,是两块不同的内存块;
浅克隆
是指复制的两个对象本身是不同的,但是属性值引用的是同一个对象;即拷贝的是同一个同象的引用;
结构型7种
适配器模式(Adapter)
对象适配器
适配器与适配者之间是关联关系
类适配器
适配器与适配者之间是继承(或实现)关系
双向适配器
在适配器中同时包含对目标类和适配者类的引用,适配者可以通过它调用目标类中的方法,目标类也可以通过它调用适配者类中的方法
缺省适配器
在不需要实现接口中所有方法时,可以使用一个抽象类去实现该接口,并提供其中方法的默认实现
在一些开源框架中应用广泛:如Spring MVC中典型的HandlerInterceptor接口和HandlerInterceptorAdapter抽象类
代理模式(Proxy)
场景
假如你是一个业主,有一套500万的房子需要出售;你希望找一个合适的客户,签个合同,收了钱,然后把房子过户给客户就可以了;
但是,有太多的客户天天找你需要看房,询问,而且大部分都是没有诚意的客户,让你不胜其烦;
业主: 只需要签字收钱就好了,剩下的事情,如果有人能帮我处理就发了;
但是,有太多的客户天天找你需要看房,询问,而且大部分都是没有诚意的客户,让你不胜其烦;
业主: 只需要签字收钱就好了,剩下的事情,如果有人能帮我处理就发了;
图形化展示
概念
为其他对象提供一种代理以控制对这个对象的访问;
本质: 引入一个中介类, 这个类实现了被代理类相同的接口或继承自被代理类,对外假装成被代理对象,帮被代理对象处理一些非必要或不能做的事情;但核心功能,仍然通过调用被代理对象来实现;
本质: 引入一个中介类, 这个类实现了被代理类相同的接口或继承自被代理类,对外假装成被代理对象,帮被代理对象处理一些非必要或不能做的事情;但核心功能,仍然通过调用被代理对象来实现;
目的
不修改原来代码的情况下,动态地给一个对象添加一些额外的职责和功能,或者添加一些控制功能,以限制对原对象的访问
本质:动态增加功能;把需要新增加的功能以代理的方式动态的添加到原对象上;
本质:动态增加功能;把需要新增加的功能以代理的方式动态的添加到原对象上;
优缺点
优点:
--松耦合
在不修改原来代码的情况下,动态的为原类增加新功能
--扩展性高
只需要增加新的代理功能类,就可以对原类不断增加新功能
--灵活
通过动态代理,不修改调用方和被调用方的情况下动态增加新功能
----------------------------------------------------------------------------------------------
缺点:
--代理实现起来可能会比较复杂
--增加了中介类,可能会对性能有影响
----------------------------------------------------------------------------------------------
最核心的目的:在不修改原代码的情况下,动态的为对象增加或减少某些功能,以及控制对被代理类的访问
--松耦合
在不修改原来代码的情况下,动态的为原类增加新功能
--扩展性高
只需要增加新的代理功能类,就可以对原类不断增加新功能
--灵活
通过动态代理,不修改调用方和被调用方的情况下动态增加新功能
----------------------------------------------------------------------------------------------
缺点:
--代理实现起来可能会比较复杂
--增加了中介类,可能会对性能有影响
----------------------------------------------------------------------------------------------
最核心的目的:在不修改原代码的情况下,动态的为对象增加或减少某些功能,以及控制对被代理类的访问
应用场景
A、远程代理
B、虚拟代理
C、Copy-on-Write 代理
D、保护(Protect or Access)代理
E、Cache代理
F、防火墙(Firewall)代理
G、同步化(Synchronization)代理
H、智能引用(Smart Reference)代理
B、虚拟代理
C、Copy-on-Write 代理
D、保护(Protect or Access)代理
E、Cache代理
F、防火墙(Firewall)代理
G、同步化(Synchronization)代理
H、智能引用(Smart Reference)代理
现实案例
spring @Aspect aop对应的实现
应用分类
JDK代理
静态代理
让代理类和目标类实现一样的接口,同时代理类中维护一个目标类对象的引用
动态代理
它是静态代理的改进,当代理接口发生改变时相应的代理对象也随之改变,让代理类实现InvocationHandler接口,动态为目标接口生成代理类
缺点:目标类必须实现接口
cglib代理
使用字节码技术(asm框架)动态创建目标类的子类作为代理类,突破了JDK代理目标类必须实现接口的限制
缺点:无法为final修饰的类或方法创建代理
装饰模式(Decorator)
背景
某些情况,当一个类已经存在,并且可以对外提供核心功能时,但是,某个时刻,希望对这个类进行功能增强(如:增加缓存);通常情况,我们可以修改原来的类,并增加对应的增强功能即可;
但是,这种方式违背了“开-闭”原则,需要修改原来的代码;而且不够灵活,如果有某个时刻又不想使用缓存,又需要修改原来的代码,显然,这不是一个很好的解决方案;
但是,这种方式违背了“开-闭”原则,需要修改原来的代码;而且不够灵活,如果有某个时刻又不想使用缓存,又需要修改原来的代码,显然,这不是一个很好的解决方案;
概念
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
本质: 引入一个中介类,这个类实现了被装饰者相同的接口,对外假装成被装饰者,并通过引用被装饰者,在调用被装饰者前后做一些附加功能(如:缓存,参数预处理);
本质: 引入一个中介类,这个类实现了被装饰者相同的接口,对外假装成被装饰者,并通过引用被装饰者,在调用被装饰者前后做一些附加功能(如:缓存,参数预处理);
目的
不修改原来代码的情况下,动态地给一个对象添加一些额外的职责和功能
本质:动态增加功能;把需要新增加的功能预先制作成零件,在需要时“动态“的添加到对象上;
本质:动态增加功能;把需要新增加的功能预先制作成零件,在需要时“动态“的添加到对象上;
优缺点
优点:
--松耦合
在不修改原来代码的情况下,动态的为原类增加新功能
--扩展性高
只需要增加新的装饰类,就可以对原类不断增加新功能
--灵活
不需要通过继承来扩展,而且可以动态增加或去除新装饰类,从而随意对原对象增加或减少某些功能
-----------------------------------------------------------------------------------------
缺点:
--额外引入第三方
-----------------------------------------------------------------------------------------
最核心的目的:在不修改原代码的情况下,动态的为对象增加或减少某些功能
--松耦合
在不修改原来代码的情况下,动态的为原类增加新功能
--扩展性高
只需要增加新的装饰类,就可以对原类不断增加新功能
--灵活
不需要通过继承来扩展,而且可以动态增加或去除新装饰类,从而随意对原对象增加或减少某些功能
-----------------------------------------------------------------------------------------
缺点:
--额外引入第三方
-----------------------------------------------------------------------------------------
最核心的目的:在不修改原代码的情况下,动态的为对象增加或减少某些功能
应用场景
扩展类的功能时
动态增加或取消某些功能时
动态增加或取消某些功能时
现实案例
JDK中的流处理;
ByteArrayInputStream
FileInputStream
ObjectInputStream
PipedInputStream
ByteArrayInputStream
FileInputStream
ObjectInputStream
PipedInputStream
外观/门面模式(Facade)
背景
我是一个辛苦一辈子的农民,攒了几十年钱,现在日子好了,也想建一套属于自己的小洋楼;首先,我要雇一个搬砖的和一个和泥的,还要一个会砌墙的人;可是我到哪里去找这些人,还要一个一个跟他们谈价钱;不知道他们和不和得来,会不会干一半不干了;哎,好烦;要是有一个人什么都会就好,我只要跟他谈,他一个人就能帮我把房子建好;
图形化展示
概念
提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使用子系统更容易使用。本质:就是化零为整;引入一个中介类,把各个分散的功能组合成一个整体,只对外暴露一个统一的接口;
目的
为了用户使用方便,把过度拆分的分散功能,组合成一个整体,对外提供一个统一的接口
优缺点
优点:
--松耦合
用户与子系统解耦,屏蔽子系统;可以提高子系统的独立性;
--使用简单
简化用户与子系统的依赖关系;
用户只与门面对接,有统一的入口;不需要知道所有子系统及内部构造;
----------------------------------------------------------------------------------
缺点:
不规范的编程方式
没有面向抽象编程,而是通过增加中介层,转换服务提供方的服务接口;
--松耦合
用户与子系统解耦,屏蔽子系统;可以提高子系统的独立性;
--使用简单
简化用户与子系统的依赖关系;
用户只与门面对接,有统一的入口;不需要知道所有子系统及内部构造;
----------------------------------------------------------------------------------
缺点:
不规范的编程方式
没有面向抽象编程,而是通过增加中介层,转换服务提供方的服务接口;
使用场景
A:简化子系统复杂性时。
B:监控所有子系统时;通过门面控制了入口,可以统一监控;
C:希望封装和隐藏子系统时;
D:两历史系统进行改造并打通关系时;
B:监控所有子系统时;通过门面控制了入口,可以统一监控;
C:希望封装和隐藏子系统时;
D:两历史系统进行改造并打通关系时;
实现案例
spring ApplicationContext;
它实现了Factory、ResourceLoader等接口,并通过引用这些接口的实例,对外统一提供:加载配置、解析资源、创建Bean、提供环境、启动流程等功能;
客户代码只需要操作context就可以获取spring的提供的功能,而无需关心内部的细节;
它实现了Factory、ResourceLoader等接口,并通过引用这些接口的实例,对外统一提供:加载配置、解析资源、创建Bean、提供环境、启动流程等功能;
客户代码只需要操作context就可以获取spring的提供的功能,而无需关心内部的细节;
桥接模式(Bridge)
组合模式(Composite)
享元模式(Flyweight)
行为型11种
观察者模式(Observer)
模板方法模式(Template)
策略模式(Strategy)
迭代器模式(Iterator)
责任链模式(Chain of Responsibility)
命令模式(Command)
状态模式(State)
访问者模式(Visitor )
中介者模式(Mediator)
备忘录模式 (Memento )
解释器模式(Interpreter)
0 条评论
下一页