一:单列模式:
单列模式是最常见的设计模式之一,主要用途是保证在整个程序中指定的对象只创建一次,始终用到的都是同一个对象。
1:懒汉模式为了保证多线程的安全性,需要加synchronized 进行同步锁,但这样就影响程序的性能
public class Singleton01 {
//类加载时不创建对象
private static Singleton01 instance;
//私有化构造方法,让它不能创建对象
private Singleton01() {
}
//创建方法返回对象
public static synchronized Singleton01 getInstance() {
//判断对象是否为空,是空就创建对象
if (instance == null) {
instance = new Singleton01();
}
//不是空就返回对象
return instance;
}
}
测试:
public class TestSingleton {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton01 s = Singleton01.getInstance();
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton01 s = Singleton01.getInstance();
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
}
}
2:饿汉模式(类加载时就创建),整个程序在运行时,有可能,没用到这个对象,这就造成了系统资源的浪费
public class Singleton02 {
//类加载是就创建对象
private static Singleton02 instance=new Singleton02();
//私有化构造方法,使其不能创建对象
private Singleton02() {
}
//创建方法返回对象
public static Singleton02 getInstance() {
return instance;
}
}
测试:
public class TestSingleton2 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton02 s = Singleton02.getInstance();
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton02 s = Singleton02.getInstance();
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
}
}
3:枚举模式(不可变的常量)
public enum Singleton03 {
INSTANCE;
}
测试:
public class TestSingleton3 {
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton03 s = Singleton03.INSTANCE;
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
try {
Singleton03 s = Singleton03.INSTANCE;
System.out.println(s.hashCode());
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
}
}
二:简单工厂模式
实现方式:
BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。
实质:
由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
实现原理:
bean容器的启动阶段:
-
读取bean的xml配置文件,将bean元素分别转换成一个BeanDefinition对象。
-
然后通过BeanDefinitionRegistry将这些bean注册到beanFactory中,保存在它的一个ConcurrentHashMap中。
-
将BeanDefinition注册到了beanFactory之后,在这里Spring为我们提供了一个扩展的切口,允许我们通过实现接口BeanFactoryPostProcessor 在此处来插入我们定义的代码。
典型的例子就是:PropertyPlaceholderConfigurer,我们一般在配置数据库的dataSource时使用到的占位符的值,就是它注入进去的。
容器中bean的实例化阶段:
实例化阶段主要是通过反射或者CGLIB对bean进行实例化,在这个阶段Spring又给我们暴露了很多的扩展点:
-
各种的Aware接口,比如 BeanFactoryAware,对于实现了这些Aware接口的bean,在实例化bean时Spring会帮我们注入对应的BeanFactory的实例。
-
BeanPostProcessor接口,实现了BeanPostProcessor接口的bean,在实例化bean时Spring会帮我们调用接口中的方法。
-
InitializingBean接口,实现了InitializingBean接口的bean,在实例化bean时Spring会帮我们调用接口中的方法。
-
DisposableBean接口,实现了BeanPostProcessor接口的bean,在该bean死亡时Spring会帮我们调用接口中的方法。
设计意义:
松耦合:可以将原来硬编码的依赖,通过Spring这个beanFactory这个工厂来注入依赖,也就是说原来只有依赖方和被依赖方,现在我们引入了第三方——spring这个beanFactory,由它来解决bean之间的依赖问题,达到了松耦合的效果.
bean的额外处理:通过Spring接口的暴露,在实例化bean的阶段我们可以进行一些额外的处理,这些额外的处理只需要让bean实现对应的接口即可,那么spring就会在bean的生命周期调用我们实现的接口来处理该bean。
三、适配器模式
实现方式:
SpringMVC中的适配器HandlerAdatper。
实现原理:
HandlerAdatper根据Handler规则执行不同的Handler。
实现过程:
DispatcherServlet根据HandlerMapping返回的handler,向HandlerAdatper发起请求,处理Handler。
HandlerAdapter根据规则找到对应的Handler并让其执行,执行完毕后Handler会向HandlerAdapter返回一个ModelAndView,最后由HandlerAdapter向DispatchServelet返回一个ModelAndView。
实现意义:
HandlerAdatper使得Handler的扩展变得容易,只需要增加一个新的Handler和一个对应的HandlerAdapter即可。
因此Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller时,只需要增加一个适配器类就完成了SpringMVC的扩展了。
四、装饰器模式
实现方式:
Spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。
实质:
动态地给一个对象添加一些额外的职责。
就增加功能来说,Decorator模式相比生成子类更为灵活。
五、代理模式
实现方式:
AOP底层,就是动态代理模式的实现。
动态代理:
在内存中构建的,不需要手动编写代理类
静态代理:
需要手工编写代理类,代理类引用被代理对象。
实现原理:
切面在应用运行的时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象创建动态的创建一个代理对象。SpringAOP就是以这种方式织入切面的。
织入:把切面应用到目标对象并创建新的代理对象的过程。