单例模式分析
六大设计原则
- 单一职责(一个类干一件事)
- 接口原则(接口方法都能用到)
- 依赖倒转(接口编程)
- 里氏替换(继承性的重写改变了,复用性差)
- 开闭原则(扩展开放、修改关闭)
- 迪米特法则(一个类对其他类保持最少的了解)
知识前景
内部类
外部类加载不会加载到内部类
每个内部类都能独立地继承一个(接口的)实现
外部类的实现与内部类无关
内部类可以使用外部类方法属性(包括私有的)
public class OIClass {
private String name ;
private int age;
public void OuterNethod(){
System.out.println("OIClass 公用");
}
class InnerClass{
private String sex;
public void InnerNethod(){
System.out.println("InnerClass公用");
OuterNethod();
}
//内部类可以用到外部类的属性
public InnerClass(){
name = "chenssy";
age = 23;
}
}
};
class Test{
public static void main(String[] args) {
//使用内部类
new OIClass().new InnerClass();
}
}
枚举(默认被final修改类,不能被继承,枚举中只有ToString没有被final修饰,枚举是自己内部实例化对象)
枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊
是因为它既是一种类(class)类型却又比类类型多了些特殊的约束。
关键字enum是一种类,编译后会生成一个继承java.lang.Enum的类
定义简单的成员变量
这种都是无参数构造函数都是public static final修饰的,类型是String,返回是成员
变量的名字,通过TestEnum.TUESDAY调用
public enum TestEnum {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY //没有成员变量,这些都是
//通过无参数构造函数创建对象
}
自定义构造函数
构造方法必须私有,防止被外部调用,有get方法才能获取到成员的值
一般可用于定义全局参数
public enum TestEnum {
MONDAY("星期一"), //这相当与是一个参的构造函数
TUESDAY("星期二"),
WEDNESDAY("星期三");
private String toDay;
private TestEnum(String toDay) {
this.toDay = toDay;
}
public String getToDay() {
return toDay;
}
}
实现抽象方法
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum TestEnum {
MONDAY("星期一") {
@Override
public String getInfo() {
return null;
}
},
TUESDAY("星期二") {
@Override
public String getInfo() {
return null;
}
},
WEDNESDAY("星期三") {
@Override
public String getInfo() {
return null;
}
};
private String toDay;
//抽象方法
public abstract String getInfo();
}
实现外部接口
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum TestEnum implements UserInterface {
MONDAY("星期一") {
@Override
public String getUsername() {
return null;
}
},
TUESDAY("星期二") {
@Override
public String getUsername() {
return null;
}
},
WEDNESDAY("星期三") {
@Override
public String getUsername() {
return null;
}
};
private String toDay;
}
单例模式
单例模式是保证应用中只有唯一一个实例存在。
Spring应用场景:创建bean的单例模式
饿汉式(线程安全,问题是消耗资源)
静态常量模式(可用)
/**
* @descritption 饿汉式
*/
public class HSingleton {
//饿汉就是类以加载就创建,比较饥渴
//类加载就创建
private static HSingleton singleton = new HSingleton();
//不予许使用new创建,私有空构造
private HSingleton(){
}
public static HSingleton getSingleton() {
return singleton;
}
}
静态代码块模式(可用)
/**
* @descritption 饿汉式
*/
public class HSingleton {
//饿汉就是类以加载就创建,比较饥渴
//类加载就创建
private static HSingleton singleton;
static {
singleton= new HSingleton;
}
//不予许使用new创建,私有空构造
private HSingleton(){
}
public static HSingleton getSingleton() {
return singleton;
}
}
懒汉式
普通,线程不安全(不推荐使用)
/**
* @descritption 懒汉式
*/
public class Singleton {
private static Singleton singleton = null;
//不予许使用new创建,私有空构造
private Singleton(){
}
public static Singleton getSingleton() {
return new Singleton();
}
}
加synchronized 方法上,虽然线程安全但是效率不高(不推荐)
/**
* @descritption 懒汉式
*/
public class Singleton {
private static Singleton singleton = null;
//不予许使用new创建,私有空构造
private Singleton(){
}
public static synchronized Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
sychronized同步块,虽然减少了锁粒度,但是并不能起到线程安全作用,因为多个线程同时越过了if (singleton == null)的条件,synchronized白加(不推荐)
/**
* @descritption 懒汉式
*/
public class Singleton {
private static Singleton singleton = null;
//不予许使用new创建,私有空构造
private Singleton(){
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized(Singleton.class){
singleton = new Singleton();
}
}
return singleton;
}
}
双重检查(推荐使用),在加锁后再进行一次if (singleton == null)判断是否容器里面真的没有对象实例。
/**
* @descritption 懒汉式
*/
public class Singleton {
private static Singleton singleton = null;
//不予许使用new创建,私有空构造
private Singleton(){
}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized(Singleton.class){
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类[推荐用,其实是一种懒汉式]
/**
* @descritption 静态内部类
*/
public class Singleton {
//不予许使用new创建,私有空构造
private Singleton(){
}
//这里实现了懒加载
private static class SingletonInstance{
private static Singleton singleton = new Singleton();
}
public static Singleton getSingleton() {
return SingletonInstance.singleton;
}
}
枚举(推荐使用)
枚举本身是个类,且是静态类,就是一个单例的
这种其实也是一种饿汉式
优点:代码简单,方便序列化
public enum Singleton {
INSTANCE;
public void dothing() {
System.out.println("做你想做的事");
}
}