1、说一下你熟悉的设计模式?
- 单例模式:保证被创建一次,节省系统开销。包括:饿汉模式(初始化时创建)、懒汉模式(调用时创建)、加锁懒汉模式、双重校验锁懒汉模式。
- 工厂模式(简单工厂、抽象工厂):主要是为创建对象提供了接口,可以应用在编码时不能预见需要创建哪种类的实例。
- 代理模式:代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。根据创建代理类的时间点,又可以分为静态代理和动态代理。
- 动态代理:使用Proxy包的newProxyInstance方法,通过反射的方式动态的生成代理类,执行委托对象的方法实质是执行代理对象的invoke方法,invoke方法中除了执行委托对象的方法,还可以自定义before、after方法,这也是spring框架中AOP的实现原理。
参考:java动态代理实现与原理详细分析 - 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。Builder构造函数带上必须的参数,可选参数单独赋值并返回一个builder对象,Lombok插件就使用了该模式来构建对象。
2、手写单例模式?
public class Emperor {
private static Emperor emperor = new Emperor();
public static Emperor getInstance() {
return emperor;
}
}
public class Emperor {
private static Emperor emperor;
public static Emperor getInstance() {
if (emperor == null) {
emperor = new Emperor();
}
return emperor;
}
}
public class SyncEmperor {
private static SyncEmperor emperor;
public static synchronized SyncEmperor getInstance() {
if (emperor == null) {
emperor = new SyncEmperor();
}
return emperor;
}
}
public class DoubleCheckEmperor {
private static DoubleCheckEmperor emperor;
public static DoubleCheckEmperor getInstance() {
if (emperor == null) {
synchronized (DoubleCheckEmperor.class) {
if (emperor == null) {
emperor = new DoubleCheckEmperor();
}
}
}
return emperor;
}
}
3、说一下双重校验锁懒汉模式?
- 如果直接在方法名使用synchronized修饰,会使得每次调用该方法都加锁,性能消耗大;
- 双重校验中,第一个if为true的时候(第一次调用)才会加锁,性能得到优化;
- 第二个if的作用:由于方法没有加锁,当多个线程同时调用该方法时,并且都通过了第一个if,则只有第一个进入锁的线程能创建实例,后面进来的线程不会多次创建实例,防止重复创建。
4、说一下工厂模式?
- 简单工厂:用来生产同一等级结构中的任意产品,对于增加新的产品,无能为力。
- 工厂方法:用来生产同一等级结构中的固定产品,支持增加任意产品。
- 抽象工厂:用来生产不同产品族的全部产品,对于增加新的产品,无能为力;支持增加产品族。