前言:单例模式的就不拿出来说了,有兴趣的小伙伴可以直接跳到 这里:面试篇:单例模式速食篇
谈谈你对深克隆(Deep clone)和浅克隆的理解
本质区别:
- 即数据克隆之后,两者之间是否存在关联
- 改变一个值是否会影响到另一个数值的变化,如果影响了那么就是浅克隆,不影响则为深克隆。
浅克隆的原则:
如果是引用类型成员变量,克隆的时候是将引用地址进行克隆。如果是值类型的成员变量,那么克隆的时候是将值进行克隆。
浅克隆常用的API
1. 工具类BeanUtils和PropertyUtils进行对象复制。
Spring的BeanUtils类中的copyProperty和copyProperties
commons的BeanUtils类中的copyProperties方法
2. 实现Clonenable接口
3. Array.copyOf(),但是在ArrayList重写了copyOf方法,实现了深克隆的效果,在方法内重新new了一个ArrayList对象。
深克隆的原则
不管是引用类型还是值类型都是复制值,重新分配内存空间。
深克隆常用的API
- 每个对象都有实现Clonenable接口并重写Object类中的clone()方法。object类默认是克隆值,重写后就可以克隆引用了。
- 序列化,必须实现Serializable接口。序列化每次都会重新分配内存空间,基于字节来操作的完全创建一个新对象。
- Apache Commons工具包SerializationUtils.clone(T Object);
- 通过JSON工具类实现深克隆。
- 通过构造方法实现深克隆(手动new对象)。
链式编程是建造者模式的标配么?
不是,官方的定义里只是说将复杂对象的构建过程跟表示进行分离,并没有说一定需要链式编程。链式编程只是对建造者模式的一种优化,因为链式编程方便我们在添加值的时候可以保证对象的引用,所有为了重复避免保存对象的引用,索性直接在添加值的时候,把被构造对象的引用返回调用者,省去了构建对象的一个过程。
链式编程的最核心思想就是可以实现零件无序装配。
你如何理解静态代理和动态代理
回答之前,先说一下什么是代理。再说下静态代理与动态代理的区别,再说下动态代理的基本实现原理。
代理是指在客户端和目标对象之间起到一个中介作用。
静态代理是一个代理只能服务于一种类型的对象,当有n个业务时,就需要n个静态对象,不利于业务的扩展。
动态代理是一个代理类可以服务于所有的业务对象,有两种实现方式,JDK动态代理以及cglib的动态代理。
JDK动态代理的基本实现原理
- 拿到被代理类的引用,并且获取它的所有接口。
- JDK proxy类重新生成一个新的类,实现被代理类的所有接口的方法。
- 动态生成JAVA代码,把需要增强的逻辑加入到新生成的代码中。
- 编译生成新的Java代码的class文件
- JVM重新加载并重新运行新的class,得到一个全新的类
CGlib和JDK动态代理对比
一般说的动态、静态的区别后,都会问jdk与cglib的区别的。就直接说答案了
- JDK动态代理是实现了被代理对象的接口,CGlib是继承了被代理对象。
- 代理类与被代理类的关系,CGlib是父与子的关系,JDK是兄弟关系。
- JDK 和CGlib都是在运行期生成字节码。
- JDK调用代理方法是通过反射机制调用,CGlib是通过FastClass机制,FastClass会提前编译好保存在某个路径下,JVM会直接加载class文件,所以不需要反射,性能比JDK更好一点。
- CGlib无法代理final修饰的方法。
什么场景下应该用策略模式,什么场景下不应该用?
适合使用的场景:需要经常自由切换执行逻辑和规则场景。
不适合使用的场景:如果两种逻辑之间关联性本来就比较大,而且变化也比较快。例如折扣活动,经常性打折的场景就不适合,这时候咱们可以通过配置来实现。
说下责任链模式的实现原理
生活中审批流程就是责任链模式,一环到一环。
实现原理
单向链表的上下文类。然后声明两个变量,一个head(头),一个尾(tail)。
Handler1 head -> next-> Handler2 -> next ->Handler3 tail
public class Context{
Handler head;
Handler tail;
}
public abstract class Handler{
protect Handler next;
}
双向链表上下文 Handler1 head -> next-> Handler2 -> next ->Handler3 tail -> prev -> Handler2
public class Context{
Handler haed;
Handler tail;
}
public abstract class Handler{
protect Handler prev; //上一个
protect Handler next; //下一个
}
可以直接用下面的总结来回答
责任链分为两种实现方式,一个是 单向链表 ,一个是双向链表。
单向链表需要设计责任链的上下文类与一个处理器handler类, handler类中需要保存责任链元素中头(head)和尾(tail)的引用,每个head需要保存下一个head的引用,这样就可以形成一个责任链。
双向链表在单向链表的基础上,在handler类中新增上一个节点(prev)的元素,引用的时候可以指向上一个接口的引用,形成一个闭环的链表。
责任链模式的优缺点是什么
优点:
-
将请求与处理解耦。
-
请求处理者将不是自己职责范围内的请求,转发给下一个节点。
-
请求发送者不需要关心链路结构,只需等待请求处理结果即可。
-
链路结构灵活,易于扩展新的请求处理节点。
缺点:
-
责任链太长或者处理时间过长,会影响整体性能。
-
如果节点对象存在循环引用,则会造成死循环,导致程序崩溃。