一、实例的创建
单例模式
模式定义:
保证一个类只有一个实例,并且提供一个全局访问点
场景:
重量级的对象,不需要多个实例,如线程池,数据库连接池。
1.懒汉模式:
延迟加载, 只有在真正使用的时候,才开始实例化。
1)线程安全问题
2)double check 加锁优化
3)编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化的实例,可以通过添加volatile 关键字进行修饰,对于volatile 修饰的字段,可以防止指令重排。
2.饿汉模式:
类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于jvm类加载机制,保证实例的唯一性(初始化过程只会执行一次)及线程安全(JVM以同步的形式来完成类加载的整个过程)。
类加载过程:
1,加载二进制数据到内存中, 生成对应的Class数据结构,
2,连接:
a. 验证,
b.准备(给类的静态成员变量赋默认值),
c.解析
3,初始化: 给类的静态变量赋初值
3.静态内部类
1).本质上是利用类的加载机制来保证线程安全
2).只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一种形式。
4.枚举类型
1)天然不支持反射创建对应的实例,且有自己的反序列化机制
2)利用类加载机制保证线程安全
工厂模式
模式定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod 使得一个类的实例化延迟到子类
应用场景
1.当你不知道改使用对象的确切类型的时候
2.当你希望为库或框架提供扩展其内部组件的方法时
主要优点:
1.将具体产品和创建者解耦
2.符合单一职责原则
3.符合开闭原则
建造者模式
模式定义:
将一个复杂对象的创建与他的表示分离,使得同样的构建过程可以创建不同的表示
应用场景
1.需要生成的对象具有复杂的内部结构
2.需要生成的对象内部属性本身相互依赖
3.与不可变对象配合使用
优点:
1、建造者独立,易扩展。
2、便于控制细节风险。
Spring源码中的应用
1 org.springframework.web.servlet.mvc.method.RequestMappingInfo
2 org.springframework.beans.factory.support.BeanDefinitionBuilder
原型模式
如果对应的类中的字段为 8 种原生数据类型,或者8种原生数据类型的包装类型,或String,BigInteger 则只需要实现Cloneable这个接口且覆盖Object.clone方法,即可利用jvm的克隆机制,完成对象的拷贝这种方式即是浅拷贝, 如果对应的类中数据为自定义数据类型,或者其他可变的数据类型(如Date,或者其 他对象类型),要借助jvm的克隆机制完成数据的拷贝,则需要实现所有的对象字段的遍历拷贝,即是深拷贝
知识点:
1.Cloneable接口/Object#clone方法 详解
2.浅拷贝/深拷贝
3.序列化机制实现深拷贝
模式定义:
指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
应用场景:
当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式。
优点:
1.可以不耦合具体类的情况下克隆对象
2.避免重复的初始化代码
3.更方便的构建复杂对象
Spring源码中的应用
1 org.springframework.beans.factory.support.AbstractBeanDefinition
2 java.util.Arrays
享元模式
模式定义:
运用共享技术有效地支持大量细粒度的对象
优点:
如果系统有大量类似的对象,可以节省大量的内存及CPU资源
JDK源码中的应用
1 String,Integer,Long...
2 com.sun.org.apache.bcel.internal.generic.InstructionConstants
二、功能的拓展和增强
装饰器模式
抽象出目标对象的接口,定义公共的能力或功能 ,装饰器通过实现抽象方法的方式拥有相应的功能,然后通过构造器传入目标对象,在目标对象实例的基础上进行拓展。
模式定义:
在不改变原有对象的基础上,将功能附加到对象上
应用场景:
扩展一个类的功能或给一个类添加附加职责
优点:
1.不改变原有对象的情况下给一个对象扩展功能
2.使用不同的组合可以实现不同的效果
3.符合开闭原则
适配器模式
模式定义:
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
应用场景
1.当你希望使用某些现有类,但其接口与您的其他代码不兼容时,请使用适配器类。
2.当你希望重用几个现有的子类,这些子类缺少一些不能添加到超类中的公共功能时,请使用该模式。
优点:
1.符合单一职责原则
2.符合开闭原则
JDK & Spring源码中的应用
JDK:
java.util.Arrays#asList()
java.util.Collections#list()
Spring:
org.springframework.context.event.GenericApplicationListenerAdapter
三、功能的解耦
策略模式
模式定义:
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式的变化独立于算法的使用者。
应用场景
1.当你有很多类似的类,但它们执行某些行为的方式不同时,请使用此策略。
2.使用该模式将类的业务逻辑与算法的实现细节隔离开来,这些算法在逻辑上下文中可能不那么重要。
3.当你的类具有大量的条件运算符,并且在同一算法的不同变体之间切换时,请使用此模式。
优点:
1.可以将算法的实现细节与使用它的代码隔离开来。
2.符合开闭原则
Spring &JDK 源码中的应用
1 java.util.Comparator
2 org.springframework.beans.factory.support.InstantiationStrategy
观察者模式
模式定义:
定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新
应用场景:
当更改一个对象的状态可能需要更改其他对象,并且实际的对象集事先未知或动态更改时,请使用观察者模式。
优点:
1.符合开闭原则
2.可以在运行时建立对象之间的关系
JDK&Spring源码中的应用
JDK:
java.util.Observable
Spring:
org.springframework.context.ApplicationListener
四、功能的组合和封装
模板模式
模式定义:
定义一个操作的算法骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
应用场景
1.当你想让客户端只扩展算法的特定步骤,而不是整个算法或其结构时,请使用Template Method模式。
2.当你有几个类包含几乎相同的算法,但有一些细微的差异时,请使用此模式。
优点:
1.你可以让客户端只覆盖大型算法的某些部分,从而减少算法其他部分发生的更改对它们的影响。
2.你可以将重复的代码拖放到超类中。
Servlet Api & Spring 中的应用
javax.servlet.http.HttpServlet
org.springframework.web.servlet.mvc.AbstractController
责任链模式
模式定义:
为请求创建了一个接收者对象的链。
应用场景:
一个请求的处理需要多个对象当中的一个或几个协作处理。
优点:
1.请求的发送者和接受者解耦
2.可以控制执行顺序
3.符合开闭原则和单一职责原则
经典案例
1 javax.servlet.Filter
2 javax.servlet.FilterChain
门面模式
模式定义:
为子系统中的一组接口提供一个一致的接口,Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
应用场景
1.当您需要使用复杂子系统的有限但直接的接口时,请使用Facade模式。
2.当您想要将子系统组织成层时,请使用Facade。
优点:
简化客户端的调用
源码中的经典应用
1 org.apache.catalina.connector.RequestFacade
2 mvc中的controller层