java需要了解的知识
2021-09-14 22:26:24 9 举报
AI智能生成
java需要了解的知识
作者其他创作
大纲/内容
数据结构
HashMap
如何进行相同key的value替换
1.计算hash
2.根据hash计算在table数组中的位置
3.尝试查找这个位置上链表中是否已存在该key,如果找到一个Entry,hash、key都相同,替换掉旧值后返回
4.将当前table位置上链表从头插入,返回
remove的过程?
1.会使用三个中间变量分别存放前一个,当前,下一个元素
2.当第一次进行比较hash,key时前一个、和当前元素相同,这个是否直接将下一个元素设置为链表头元素即可返回
3.其他情况就是不同的遍历链表之后,将前一个和下一个元素进行链接即可返回
hash如何定位table?
hash值与table最大下标进行&运算
List
ArrayList
就是内部在针对数组进行处理,将对象放入一个数组当中,当数组长度不够时将对数组长度自动扩展
由于对数据长度修改时涉及到对数据的复制以及位置的腾挪,在这个过程中会非常消耗内存和CPU资源
对于ArrayList中数据的重新排列都是由System.ArrayCopy()函数完成的
LinkedList
维护一个链表,直接持有头节点与尾节点引用
size()实现
每次对LinkedList修改都会对内部变量size作修改,当被调用时直接返回size的值
优点:当对首尾节点做修改时,非常容易,比ArrayLsit消耗的内存资源更少
缺点:当需要对中间节点修改时,会相对ArrayList消耗更多时间
ArrayList与LinkedList的性能区别?以及产生这种现象的原因?
1.数据结构
ArrayList是数组
LinkedList是链表
2.资源消耗
由于ArrayList中实际是维护一个数组,当数组长度需要修改时,需要额外创建一个数组,并且当长度修改,特别是移除的时候,会产生很多垃圾,引起系统频繁GC
LinkedList只需要创建节点对象,最多修改三个节点之间的引用
ArrayList
数组定长
数组长度改变都需要额外创建一个数组
频繁修改数组长度,会频繁创建新数组,大量旧数组成为垃圾资源,引起系统频繁GC,导致性能下降
3.查找指定位置元素消耗时间
ArrayList可以直接操作数组得到
LinkedList需要遍历,消耗时间比ArrayList相对较长
堆、栈、队列的区别
不同点
堆:数据按照一定的优先顺序进行排列,从堆低插入,堆顶出,
栈:类似于桶,先进后出,后进先出
队列:先进先出,FIFO(First In First Out)
多线程
什么是线程?
线程有哪些初始化方法?
Thread类中wait()、sleep()、join()、interrupt()、stop()方法的作用
线程如何实现数据共享?
如何实现同步?
锁的种类
悲观锁
对资源持悲观态度
认为写多读少,每次需要确定获取到锁才会去执行后续的操作
乐观锁
自旋锁
当没有获取到锁时,会进行空转而不会进入阻塞状态
消耗一定的CPU时间,但是不会又上下文同步的额外时间
会一直占有CPU时间,当资源竞争激烈时,会严重消耗资源,反而引起性能下降
当自旋锁总是等待空转,那么会自动膨胀为悲观锁
偏向锁
使用偏向锁时,CPU会比正常的申请锁过程多一步,设置偏向锁标记
当持有偏向锁的线程重复进行锁申请时无须再次进行cas操作,可以直接执行,当下次申请时仍然是这样
当锁资源竞争激烈时CPU每次都需要重新检查线程ID是否与上次一致,并且设置偏向锁标记
多出来的步骤会影响性能
获取
撤销
设置
轻量级锁
加锁
准备
JVM会为线程在栈桢中开辟一小块内存,用来存放线程获取的对象的锁记录
过程
线程会将对象的MarkWord复制之前开辟的内存中保存起来,并将此记录的指针通过CAS操作替换到对象头中的MarkWord
结果
成功
那么就是成功获取到锁
失败
那么做自旋操作重试获取锁,自旋操作获取仍然失败,轻量级锁将膨胀为悲观锁
解锁
过程
线程将重新把对象头中的MarkWord的指针信息读取到锁记录中原来的MarkWord,通过CAS重新进行替换操作
结果
成功
释放锁,结束
失败
那么就是有其他线程竞争过锁,那么会释放锁,并尝试唤醒陷入阻塞状态的线程
膨胀条件
使用CAS操作将对象头中的MarkWord替换时,如果失败则转为自旋锁获取锁,仍然失败则会膨胀为阻塞锁
java对象头
MarkWord
前30bit
构成
25bit 对象的Hash值
4bit 分代年龄
1bit 偏向锁标记
加锁
轻量级锁
线程栈桢的锁记录指针
重量级锁
互斥量的指针
GC
空
偏向锁
线程ID
Epoch
分代年龄
偏向锁标识
2bit 锁标志位
00
轻量级锁
10
重量级锁
11
GC标记
01
偏向锁
class matedata address
对象类型数据的指针
ArrayLength
如果对象是数组,那么记录数组的长度,如果不是则没有
线程池的原理
常用的线程池有哪些
fixed线程池与Cache线程池的区别是什么
线程池的作用以及好处有哪些
对于多线程中所使用到的组件
ThreadLocal
作用、实现原理
作用
对让线程持有线程自己的数据
实现原理
会通过Thread.currentThread()获取调用的线程,然后通过线程获取ThreadLocalMap
ThreadLocalMap通过当前ThreadLocal获取对应的ThreadLocalMap.Entry,这样的好处是,即使ThreadLocal被多个线程共享,但是ThreadLocalMap是不同的,ThreadLocal仍能获取为当前线程获取到线程自己的变量
使用场景
为每个线程提供独立的数据读写,提高读写速度
缺点
使用不当会引擎内存泄漏,清理ThreadLocal中的垃圾时需要调用remove(),set(),get()
问题:为什么一定要在调用操作数据的方法才能防止内存泄漏
J.U.C
ConCurrentHashMap
实现原理
为什么是线程安全的
为了多线程操作数据,针对锁做了哪些优化
volatile关键字
实现原理
作用
sun针对此关键字做过的优化
CAS(Compare And Swap):比较与替换
通过使用系统底层的机制完成预期值与当前值相同时,将更新新值的整个操作
这个操作是通过现代CPU的特殊指令实现对读-比较-写操作的实现
优点
可以通过CAS操作实现无锁化
缺点
ABA问题
可通过对数据添加版本号,来防止ABA问题
通过自旋不停的尝试compare-and-wap操作,直到成功
Spring
spring框架有哪些组件
Spring Core
提供对bean的发现,创建,管理方法实现的工具包,是被调用的工具,不会主动的去执行这些方法
Spring web
Spring Aop
全称
Aspect Oriented Programming 面向切面编程
概念
OOP
OOP提供了封装、继承、多态的特性,建立一种对象层次结构,用于模拟公共行为的一个集合,抽象出来的公共行为往往是一种纵向的关系
AOP
某些业务相同,但是会分布在OOP编程中的各个纵向层次,产生了大量重复的代码,所以,AOP就是为了抽象出这种在纵向层次难以抽离的业务而提出来的新的编程思想
将那些影响了多个类的公共行为封装到一个可重用模块
概念名词
横切关注点
在哪里拦截、拦截之后的处理,这些特殊的点就叫横切关注点
切面
类是对物体特征的抽象,切面则是对横切关注点的抽象
连接点-joincut
被拦截的点,目前Spring仅支持方法最为连接点,但是实际上还需要构造器、甚至字段上的抽象这种更加复杂的连接点需求
切入点-pointcut
对拦截点进行拦截的定义
通知-advice
就是拦截点拦截之后的处理行为的代码,通知有五种方式:前置、后置、异常、最终、环绕
目标对象
代理的目标对象
织入-weave
将切面应用到目标对象,且创建代理目标对象的过程
引入-introduction
在不修改代码的前提下,在运行时期,为类添加一些方法或字段
实现
Spring中,Aop由SpringIoc进行管理,应用关系也有Ioc梳理
拓展
jdk动态代理
只能代理接口,无法直接代理一个类,通过InvocationHandler接口将调用代理,在invoke的方法中对Target调用
利用反射进行方法的代理
cglib工具动态代理
通过asm工具包,动态生成被代理类的子类的.class文件,集成被代理类,可以代理非final修饰的任意类,
Spring可以强制使用CGlib进行动态代理,需要在配置文件中配置,默认情况下使用jdk动态代理,但是jdk动态代理的时候bean是由SpringIoc进行初始化的,否则必须使用Cglib
应用场景
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 懒加载
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
Spring Ioc
概念与原理
Inversion of Control
控制反转,是为了解决对象与对象之间的依赖关系的一种编程思想,简单的理解模型就是两个对象通过一个第三方对象,解决了依赖对象与被依赖对象的耦合关系
Dependency Injection
相当于是对控制反转思想的一种实现的补充
谁依赖谁
实现上,那么就是依赖对象依赖容器
为什么需要依赖
因为是容器给依赖对象提供被依赖的资源
谁注入谁
容器为依赖对象注入被依赖对象
注入了什么
容器为依赖对象注入所需要的外部资源,如对象,常量等
相关组件
BeanFactory
ListableBeanFactory
结构行为
HeirarchicalBeanFactory
继承行为
ConfigureableBeanFactory
AutowireCapableBeanFactory
装配行为
这些接口最终会被DefaultListableBeanFactory实现
作用:只是针对IOC容器的基本行为做出限定,但是并不对bean的初始化过程产生影响
具体的bean初始化过程由不同的IOC容器实现,最简单的就是XmlBeanFactory,比较高级的IOC容器就是ApplicationContext
BeanDefinition
此接口主要是为IOC容器提供bean之间关系的描述,IOC容器根据这个类的实现类来初始化Bean
IOC的初始化过程示例
FileSystemXmlApplicationContext
new (String ... configureLocals)
super(parent)
setConfigurations([])
Bean关系以及属性描述配置文件的文件路径,分别可以制定多个或者单个
refresh()
过程
作用
IOC依赖注入的时间
赋值注入
通过setter方法,来实现实例的属性注入,使用这种方式时,需要又无参构造函数的声明,否则会抛出异常
构造注入
直接通过构造函数,在实例被构建时注入依赖
工厂注入
通过相关的静态工厂将参数通过工厂类中的初始化方法,进行依赖注入
Autowire自动注入
通过BeanPostProcessor,当扫描到有类的参数上带有@Autowire时会自动进行类型或者bean名称进行匹配
@Autowire可以注解构造函数,这个时候,会直接在容器中找到类型匹配的参数,进行初始化被注解的Bean
应用场景
Spring Context
主要是使用SpringCore中提供的对Bean管理的方法,并且保存这些bean关系的环境,而这个环境在Context的管理下,构成了一个Ioc容器,管理Bean中间的关系,以及声明周期
JDBC
ORM框架
Mybatis
Mybatis标签、配置
与Hibernate相比有哪些优点缺点?
Hibernate
Spring MVC
原理、作用
注解的使用
@Service
@Controller
@ResponseBody
@Request
……
SpringMVC基本工程结构
Model
Controller
dao
Service
获取请求中的参数
get请求直接映射到形参,参数名称需要与形参名称一致,只能get请求
HttpRequestServet中通过getParamter(“name”)获取,get/post都可以
直接将参数转换成Bean接受,post/get都可以使用
@ModelAttribute注解,直接注解形参,只能接受post的from表单数据
@RequestParam注解,直接注解形参,post/get都可以,但是当请求中可能不含某个参数时,需要加上required=false属性
通过HttpServletRequest的getQueryString()获取参数,只能get请求
FactoryBean与BeanFactory的区别
BeanFactory与Spring中ApplicationContext的区别
ApplicationContext的特点
Spring的事物管理
事物管理
隔离级别
DEFAULT
默认隔离级别,一般等同于READ_COMMITED级别
READ_UNCOMMITED
可以读取到有数据修改,但是还未提交的事物,不能防止脏读,重复读取,和幻读
READ_COMMITED
只能读取到其他事物已经提交后的数据,可以防止脏读,是绝大多数时候推荐的级别
REPEATABLE_READ
指事物可以重复执行某个查询过程,每次返回相同的结果,可以防止脏读和不可重复读
SERIALIZABLE
分支主题
事物传播属性
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
PROPAGATION_MANDATORY
PROPAGATION_REQUIRES_NEW
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
注解@Transactional
属性
value
propagation
isolution
readonly
rollbackFor
rollbackForClassName
noRollbackFor
noRollbackForClassName
使用
类,接口,方法等
只有在代理类调用被注解方法等才会生效
必须用到AOP切面配置了,或者动态代理技术
jvm
内存
jvm内存结构
线程私有区域
PC寄存器或者程序计数器(Program Counter Register)
每个线程都会创建一个寄存器,总是指向下一条指令,但是执行本地方法时为空
本地方法栈
当调用线程本地方法时,保存局部变量表,和本地方法的栈桢
本地方法
非java语言实现的方法,这些方法主要是为了java在与系统以及硬件交互时能有较高的效率而用C或C++编写的方法
栈内存
用来保存线程自己的局部变量、常量等信息
构成
桢
一个栈是由一系列桢组成线程每调用一个方法都会创建一个桢
,这个桢会保存这个方法的局部变量、常量池指针
主要信息
局部变量区
概念
一组变量值的存储空间,存储空间的容量大小在class文件被编译时,方法的code数据决定了方法的最大
主要保存信息
java方法参数
java方法内部局部变量
保存的形式
分支主题
操作数栈
作用
由于java中没有PC寄存器,并且也无法通过指令访问到PC寄存器,所以java是通过操作数栈来获取操作数数据的
数据是以标准的压栈出栈操作进行访问的而非索引,而局部变量区访问数据的方式是以数组的形式访问索引
线程共有区域
方法区
主要是存储加在的类的信息,堆通过对方法区类信息在内存中分配内存区域保存按照类创建的实例
堆内存
结构特点
作用
堆、栈在内存中的主要区别在哪
队列的特点
相同点
不同点
GC
gc算法
引用计数法
根据引用计数,当引用计数为0时被视为垃圾,将会被回收
缺点
计数计算的加减影响性能
无法处理循环引用
标记-清除法
会先从根节点出发,标记根对象不可触及对象,然后清理
缺点
会直接清除,但是可触及对象会散布在内存中,产生大量的内存碎片,后期内存使用率低下
标记-压缩法
标记跟对象不可触及对象,然后清理,在将可触及对象移动到内存的一端
内存使用率提高,内存碎片大大减少
缺点
会将消耗大量时间,影响性能
标记-复制法
将内存分成两块,只是用其中一块,当清理垃圾时,将可触及对象直接复制到另一块内存中,之后清空需要回收的那一块内存
比标记压缩法更加高效
缺点
内存只能使用一半,造成浪费
标记-复制法整合标记-压缩
内存分为三个区域,两块新生代内存,一块老年代内存,新生代中使用标记-复制法回收资源,老年代中使用标记压缩法回收资源
将对象回收方式分类,尽可能的选择相对高效回收算法提高效率,以及内存的使用率
缺点
需要对对象的年龄以及大小进行管理,策略比较复杂,而且仍然会浪费一些内存
CMS GC算法
拓展
stop-the-world
jvm停止运行,java代码不执行,native方法正常执行,但是当前无法与jvm进行交互
原因
触发GC
死锁检查
dump线程
堆的dump
内存非配配置
堆
-Xms 最小堆内存
-Xmx 最打堆内存
栈
-Xss 栈内存大小
永久代内存
相关的虚拟机指令
-XX:PermSize
分配永久代内存
-verbose:class
-XX:TraceClassLoading
类的加载日志
-XX:TraceClassUnLoading
类的卸载日志
特别说明
主要是类的信息,以及类中的静态变量和常量信息
主要是在jdk7中的hotspot虚拟机中才有
在jdk8中类的信息会被放到与堆内存不相关的本地内存中,这块区域叫做 元空间(matespace)
Perm空间的内存所在区域在堆中分配
堆内存与栈内存的区别
class的加载机制
classLoader
常用的有哪些classLoader
classLoader加载类的过程
类的加载时机
概括
一个类仅在初始化前才会被加载
全局区域
引用类实例初始化之后,按照从上往下的顺序,加载类的信息,初始化
局部变量
引用类的实例执行初始化了类的实例前加载类的信息
仅声明不会将类加载到Perm区或者元空间
数据库
Mysql
锁
乐观锁
悲观锁
锁事物处理等级
引擎
InnoDB引擎
事务处理
事物日志
崩溃修复
多版本并发控制
MyISAM引擎
持久化
frm
表的结构
MYD
存储数据
MYI
存储索引
存储格式
静态
字段是固定长度
动态
字段长度可变
压缩
数据占用最小
MEMORY引擎
持久化
frm
表的结构
内存
MYD
MYI
数据库设计
数据库的设计范式
优化
表优化
横向切割/水平切割
纵向切割
表字段不宜过多
建议值20以下
索引的使用
尽量减少字符串字段建索引
如果数据种类不多,尽量不要这个字段做索引
数据量少不要使用索引
分表的优点缺点描述
字段优化
存储类型尽量选择小的
可提高读取及存取空间
字符串数据尽量使用枚举类型
时间字段尽量使用timestamp
Datetime存储的时间会有缺失,只会存日期和时间
varchar尽量压缩,不要给冗余长度
如果可以尽量不要使用数据库自己的约束而是使用逻辑约束,减少数据库逻辑处理的工作
sql优化
查找慢查询
数据库连接池
druid
作用
优点
配置
负载均衡
nginx
作用
如何使用以及配置、安装
使用场景
RPC
api网关
ESB服务总线
Dubbo
session保持方式
session保持
nginx根据Cookie将请求始终发往同一个节点
session复制
将session放在统一的位置,所有新节点都去获取,新的会话添加,失效会话删除
建立虚拟节点,然后每个虚拟节点后是一个集群,各个集群内部管理集群内部的session,新节点添加到虚拟节点中
session共享
所有session交给另一个系统管理,所有节点通过网络IO方式查询session
缓存
作用
使用场景
代表性的组件
redis
如何使用
配置、安装
集群部署
消息队列
原理
作用
使用场景
代表性工具
hornetq
kafka
ActiveMQ
RocketMQ
说明这些中间件的差别
分布式服务框架
原理
使用场景
SpringCloud
原理
使用
配置
搭建
优点
缺点
dubbo
原理
使用
支持的协议
缺省协议
默认协议
单一长连接,TCP传输协议
hessian序列化
使用场景
适合多消费者,少提供者的服务场景, 在高并发下不适合传输大数据,如文件或着长文本等内容
rmi协议
JAVA标准远程调用协议
http协议
thrift协议
hessian协议
webservice协议
memcache协议
redis协议
注册中心
zookeeper注册中心
在zookeeper目录下保存注册服务信息
可以使用zookeeper对客户端进行权限限制
nulticast注册中心
服务自己发出广播,让客户端进行发现和绑定
不安全,可能会引起错误注册,以及错误调用
redis注册中心
当dubbo服务已经订阅以及注册之后,注册中心服务器挂掉,不会影响dubbo客户端和服务端的调用和消费, 注册中心可以堪称只是一个保存节点信息的一个远程目录, 当客户端与服务端的之间绑定完成之后,交互只会发生在服务端和客户端, 但是如果这个时候有新的服务,或者节点需要注册并且被订阅,那么就会有影响了
错误处理
Failover cluster
当调用失败时会对下一个节点进行重试调用, 若多次调用均失败会让响应等待时间过长,消耗服务器资源, 建议重试次数不要太高
Failfast cluster
如果调用失败立即返回
Failback cluster
调用失败后返回,标记之后,可能会进行下一次重试
Failsafe cluster
调用失败后忽略,用于记录日志
Froking cluster
同时调用多个节点,如果有返回成功的立刻返回
broadcast cluster
调用多个节点,如果一个返回失败,那么立刻失败,除非所有的节点都返回成功
配置
搭建
优点
缺点
SpringCloud与Dubbo的区别
分布式一致性Hash算法
大数据相关组件(此部分仅需了解)
ZooKeeper
原理
使用
作用
Spark
使用
使用场景
Hadoop
使用
配置
使用场景
Sevlet
Servlet作用
接受客户端请求,根据请求参数,动态生成html文件,然后返回给客户端的一个服务器应用程序
Servlet的初始化过程
服务器servlet容器启动,根据配置会加载servlet,当第一次请求时会判断有无servlet实例,然后初始化实例 然后执行inti()方法初始化servlet,之后使用service()处理请求,这个时候除了执行部分模版方法,还会执行 自定义的doGet或doPost等方法,然后响应客户端请求,当服务器不再需要servlet实例时,将会执行destroy()方法 然后停止服务
servlet的生命周期
init()
加载servletConfig,web.xml中的各种配置
service()
其实是调用service(HttpRequestServlet request,HttpResponseServlet response)方法这个方法执行过程中,真正的处理方式是在doxxx()用户自定义的方法中那个
destroy()
销毁servlet,由tomcat调用,但是被调用后只是释放部分资源,不会直接销毁servlet实例, 实例具体的销毁时间暂时不明
Servlet是否线程安全
非线程安全
tomcat的请求处理方式是请求先全部put到队列当中,然后多线程取,然后交给同一个servlet处理
由于JVM的线程内存模型,导致当servlet中对全局变量使用方式不当时,会产生线程不安全的错误
那么从而也可以推论http请求也是非线程安全的,如果servlet处理请求时将请求信息和响应信息错误的放到全局变量中, 且没有正确使用时,http非线程安全是必然的
jsp
jsp的九大内置对象
out
request
response
session
application
page
exception
pageContext
config
JSP、Servlet的区别
都是为了能构动态的生成html文件,但servlet是纯java代码生成,而JSP则是由java+html混合
servlet生成html文件是一行一行打印,而jsp则是生成一段嵌入到现有的html文件中,比servlet更加效率
servlet对请求的处理流程分的更加详细,而jsp则只是对数据进行加工
servlet与view层完全分离,而jsp则相对模糊
断点续传的实现原理
TCP/IP协议
http协议
http协议特点
请求
请求行
请求方式,url资源地址,http版本好
请求头
cookies,user-agent等各种客户端信息
空行
请求体
请求数据
响应
状态头
http版本号,状态码
响应头
各种服务器的相关信息
响应体
响应数据
http协议的过程
建立链接
TCP/IP三次握手四次挥手
发送报文
收到报文
解析报文
展示
http协议实现是否是线程安全的?
原因
那https是否是线程安全的
各种状态码的意思
短链接的实现原理
思考题:如何确保数据传输中不丢失数据?
描述TCP/IP协议的三次握手四次挥手过程
建立链接(握手)
客户端:请求
服务端:收到,我说的什么
客户端:你说的是这个
断开链接(挥手)
客户端:断开
服务端:好的
服务端: 断了
客户端: OK
粘包和拆包
原因
TCP是传输层协议,对TCP协议来说数据块是无结构的,无边界的,所以当数据发生
从TCP包的帧结构,TCP没有数据长度设计,造成应用层无法判断数据的起始点与终结点
TCP会有将多次间隔较小,数据量小,连续发送的包合并成一个大数据包发送
出现场景
拆包
发送数据大于缓冲区剩余空间
发送数据大于MSS限定长度
粘包
数据长度过短,造成缓冲区被多次写入
接收方没有及时接受缓冲区中的数据,造成缓冲区多次写入
解决方法
拆包
对每个数据包的包首部添加数据长度,让应用层便于解析
通过特殊符号,区分数据块
粘包
发送方
每次数据写入缓冲区时,将缓冲区的剩余空间沾满,让缓冲区无法被多次写入
关闭了TCP自身优化,增加了带宽负担
强制使用TCP的push指令将缓存区的数据发送出去
关闭了TCP自身优化,降低了网络传输的效率
接收方
人为设计,将每次接收工作精简优化,尽量及时接收
只能尽量避免,不能彻底杜绝
对数据任务分段,多次接收,自行合并
影响效率
数据包中自带边界信息,接受方进行预处理后交给应用层
每次发送数据后将连接关闭然后重新建立链接
UDP
UDP的每个数据包,会有16bit的数据标识数据长度,而且不会有优化算法将数据包合并一个发送
七层模型
应用层
网络接口
表示层
数据的压缩,格式,加密解密
会话层
会话的建立,维持,终止
如http、websocket等各种链接协议
传输层
TCP/IP协议
网络层
逻辑寻址
如IP,IPv6等逻辑地址的定义
链路层
建立逻辑链接
物理层
物理链接的建立,维护,断开
设计模式(选择常用部分了解,并且尝试描述)
创建型
Singleton(单例)
Prototype(原型)
Factory(工厂)
AbstractFactory
Builder(建造者)
结构型
Adapter(适配器)
Bridge(桥接)
Facade(门面/外观)
Composite(组合)
Decorator(装饰)
Proxy(代理)
Flyweight(享元)
行为型
Mediator(中介者)
Observer(观察者)
Iterator(迭代器)
Visitor(访问者)
Chain of Responsibility(责任链)
Memento(备忘录)
State(状态)
Interpreter(解释器)
0 条评论
下一页