UML
- Unified modeling language,统一建模语言
- 类图,描述类与类之间的关心,最核心
- 六种类的关系
依赖,Dependence,A用到了B类,A依赖B类;类的成员属性、方法的返回类型、方法的参数、方法中使用到
泛化(继承),generalization,依赖关系的特例;A类继承B类
实现,Implentation,依赖关系的特例;A类实现B类
关联,Association,依赖关系的特例,具有导航性,具有双向关系或单向关系
聚合,Aggregation,关联关系的特例,表示整体和部分的关系,整体和部分是可以分开的,可以分开的就是聚合的关系。B作为A的成员变量或者方法参数,通过setter方法设置,B聚合于A。例子,电脑鼠标键盘
组合,Composition,关联关系的特例,不可分离,整体和部分的关系,整体和部分不可分开;A实例化的同时,B实例化,共生共死;如果A类中,定义了对B类的级联删除(删除一个对象,必须把另一个对象删除),那么就是组合关系,同生共死
类成员案例
@startuml
class Test{
- name
- age
+ Test()
+ setter()
+ getter()
}
note right of Test : -私有,+公共
@enduml

类关系案例
@startuml
interface Class
A ..> Class : 依赖
B -- Class : 关联
C --|> Class : 泛化、继承
D ..|> Class : 实现
E o.. Class : 聚合
F *.. Class : 组合
note top of B : 特例包括聚合、组合
note top of E : 通过setter方法传递
note top of F
Class是F的一个属性,
当F被实例化后,Class也被实例化
耦合性比聚合强一些
end note
@enduml

单例模式
- 采取一定方法,保证某个类在整个软件系统中,只存在一个对象实例,只提供一个获取其对其实例方法(静态方法)
- 八种写法,推荐使用
饿汉式、双重检查、静态内部类、枚举
饿汉式(静态常量)
- 构造器私有化(防止new)
- 类的内部创建对象
- 向外暴露一个静态的公共方法
getInstance
class Singleton {
private Singleton() {
}
private final static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
- 优点,比较简单,在类装载时(初始化阶段)就完成了类的实例化,避免了线程同步问题
- 缺点,在类装载时完成实例化,没有达到懒加载
Lazy Loading的效果,如果从开始到结束都没有使用这个实例,会造成内存的浪费
- 通过
类加载避免了线程同步问题,但是有多种原因导致类装载,不能保证这个单例对象懒加载,可能造成内存浪费
饿汉式(静态代码块)
class Singleton {
private Singleton() {
}
private static Singleton instance;
static {
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
懒汉式(线程不安全)
- 优点,起到懒加载的效果,但是只能在单线程下使用
- 缺点,在多线程下,一个线程进入了if语句的判断,但是还没有往下执行;另一个线程也通过了这个判断,会产生多个实例
- 在实际开发中,不要使用
class Singleton {
private Singleton() {
}
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式(线程安全,同步方法)
- 解决了线程不安全的问题
- 效率太低了,每个线程都想获取类的实例的时候,都要进行同步,要进行等待
- 实际开发中,不推荐使用
class Singleton {
private Singleton() {
}
private static Singleton instance;
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式(线程不安全,同步代码块)
- 本意是对第四种方式进行改进,但是并不能起到线程同步的作用
- 线程安全都无法保证,都会进入if语句,进行等待,并产生多个实例,不能使用
class Singleton {
private Singleton() {
}
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
}
双重检查
volatile 让修改内容立即更新到内存,一个线程更新完毕,其他线程立即同步;防止指令重排,创建一个对象需要三条指令,可以会发生重排,导致引用指向了分配的地址,但对象还未创建完毕,判断校验不准确;保证操作在主存中进行
new、dup、invokespecial
double-check保证了线程安全,懒加载,效率较高
- 推荐使用
class Singleton {
private Singleton() {
}
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
静态内部类
- 类装载时,不会主动装载静态内部类,直到静态内部类被使用
- 静态内部类装载时,是线程安全的
- 类的静态属性只会在第一次加载类的时候初始化,内部类里面的东西不会被初始化
- 避免了线程不安全,利用静态内部类的特点实现延迟加载,效率高
- 推荐使用
class Singleton {
private Singleton() {
}
private static class SingletonInstance {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
枚举
- 避免多线程同步问题,防止反序列化重新创建新的对象,推荐使用
- 反序列化,把字节序列恢复为Java对象的过程,存在不可信数据进行反序列化,让程序产生非预期的对象,对程序进行破坏
- 反射,将类信息转换成属性,可以调用私有方法
enum Singleton {
INSTANCE;
public void say() {
System.out.println("instace");
}
}
源码
- runtime,饿汉式创建

注意事项
- 单例模式保证了内存中该类只有一个对象,节约了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式提高性能
- 场景:创建对象耗时过多,消耗资源过多
(重量级对象);经常用到的对象,工具类对象,频繁访问数据库或文件的对象(数据源、session工厂)