设计模式
1. 单例模式
推荐直接使用饿汉式,不存在线程安全问题
单例模式懒汉式存在的问题
1.1 如何避免单例模式被破坏
避免破坏单例
单例模式被破坏主要有三种:
- 使用反射拿到对象,因反射最终还是调用了构造方法,只不过是有了更大的权限,调用的是private的构造方法,所以只需要在构造函数中抛出异常即可
- 使用clone方法,同理,在clone方法跑出异常
- 反序列化,反序列化会调readResolve,用在类中写上readResolve方法,方法直接返回单例
public class Singleton implements Serializable {
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
protected Object readResolve() {
System.out.println("---------------------------readresolve_______");
return instance;
}
}
2 适配器模式
2.1 缺省适配器(接口适配器)
注意: 缺省的适配器设计模式和JDK8之后引入的一个新功能是一样的,JDK8中允许接口中有方法的实现,也即default方法。所以在jdk8中,可以直接使用这一特性取代缺省的适配器模式。
举例:springboot中WebMvcConfigurerAdapter已经标记为废弃,就是因为它采用的是缺省适配器模式,如果使用jdk8,可以直接实现WebMvcConfigurer ,不需要再WebMvcConfigurerAdapter 继承适配器,一下spring官方注释有说明
/**
* An implementation of {@link WebMvcConfigurer} with empty methods allowing
* subclasses to override only the methods they're interested in.
*
* @author Rossen Stoyanchev
* @since 3.1
* @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
* possible by a Java 8 baseline) and can be implemented directly without the
* need for this adapter
*/
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
}
2.1.1 缺省适配器(接口适配器)模式实现方式:
- 创建一个XXX接口,里面有若干方法;
- 创建一个XXXAdapter抽象类,实现XXX接口所有方法,不过方法体都是空的,没有具体实现
- 创建自己的业务类,实现XXXAdapter,重写需要用到的方法
2.1.2 缺省Adapter作用解释
- 一个接口有N多方法,可能我们需要的只是其中一个,如果直接实现接口,会造成每次都要实现一堆我用不上的方法,所以搞一个中间的Adapter帮我们实现所有方法,尽管没有方法体。
- 必须使用抽象类!!因为抽象类无法被实例化,这就提醒我们使用的时候必须要对Adapter进行实现,实现了以后我们只需要重写我们想用的那个方法即可,而不用重写一堆没用的。
2.2 类适配器
2.2.1 场景举例
手机(客户端)充电要用10V电压(目标),而我国直接提供的电压是220V(源头),现在给手机充电就需要把220V电压先转换成10V,这就需要用到充电头(适配器)来转换。
2.2.2 实现
- 有一个已存在的类,并且被其他代码多次使用,在新的代码中也要使用到它,不过不能直接使用,需要改造;——源
- 有一个接口,这个接口是新代码中要直接用到的;——目标
- 源和目标不一致,需要实现从源到目标的转换,转换工具就叫做Adapter——适配器
- 适配器需要继承接口(目标),同时实现类(源),重写接口(目标)中的方法,方法中的具体内容就是转换源——》目标。
2.2.3 代码
//目标电压
public interface Voltage5V {
int out5V();
}
//源头电压
public class Voltage220V {
public int out220V(){
return 220;
}
}
//适配器进行电压转换
public class Adapter extends Voltage220V implements Voltage5V{
@Override
public int out5V() {
System.out.println("适配器进行电压转换");
return out220V()/22;
}
}
//客户端
public class Phone {
public void charge(Voltage5V v){
System.out.println("开始充电");
System.out.println("充电电压," + v.out5V());
}
public static void main(String[] args) {
Phone phone = new Phone();
phone.charge(new Adapter());
}
}