23种设计模式-单例模式
GoF 23
是一种思维 ,一种态度,一种进步
创建型模式:
单例模式、工厂模式、抽象工厂模式、创造者模式、原型模式。
结构型模式:
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:
模板方法模式,命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式责任链模式、访问者模式。
OOP七大原则
开闭原则:对扩展开放,对修改关闭
里氏替换原则: 继承必须确保超类锁拥有的性质再子类中依然成立
依赖倒置原则:要面向接口编程,不要面向实现编程。
单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性。
接口隔离原则:要为各个类建立他们需要的专用接口
迪米特法则: 只与你的直接朋友交谈、不跟“陌生人”说话。
合成复用原则: 尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
单例模式
饿汉式单例
package single;
public class Hungry {
//可能会浪费空间
private byte[] data1 = new byte[1024*1024];
private byte[] data2 = new byte[1024*1024];
private byte[] data3 = new byte[1024*1024];
private byte[] data4 = new byte[1024*1024];
private Hungry(){
}
private final static Hungry hungry = new Hungry();
public static Hungry getInstance(){
return hungry;
}
}
DCL 懒汉式
package single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
//懒汉式单例
public class LazyMan {
private static boolean yp = false;
private LazyMan(){
synchronized (LazyMan.class){
if (yp == false){
yp = true;
}else {
throw new RuntimeException("不要试图使用反射破坏异常");
}
}
// System.out.println(Thread.currentThread().getName()+"ok");
}
private volatile static LazyMan lazyMan; //这里加上volatile 避免指令重排
public static LazyMan getInstance(){
//加锁 双重检测锁模式的 懒汉式单例 DCL懒汉
if (lazyMan==null){
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan = new LazyMan();// 不是一个原子性操作
}
}
}
return lazyMan; //
}
//反射
public static void main(String[] args) throws Exception {
// LazyMan instance = LazyMan.getInstance();
Field yp = LazyMan.class.getDeclaredField("yp");
yp.setAccessible(true);
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyMan instance = declaredConstructor.newInstance();
yp.set(instance,false);
LazyMan instance1 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance1);
}
}
/*
* 1,分配内存空间
* 2,执行构造方法,初始化对象
* 3,把这个对象指向这个空间
*
* 123
* 132 A
* B//此时lazyMan家没有完成构造 B线程会认为lazyMan不等于null,而执行了return
*
* */
//单线程下确实单例ok
//多线程并发下会出问题
// public static void main(String[] args) {
// for (int i = 0; i < 10; i++) {
//
// new Thread(()->{
// LazyMan.getInstance();
//
//
// }).start();
// }
// }
静态内部类
package single;
//静态内部类
public class Holder {
//单例模式首先进行构造器私有
public Holder() {
}
public static Holder getInstance(){
return InnerClass.holder;
}
public static class InnerClass{
private static final Holder holder = new Holder();
}
}
单例不安全 因为有反射
枚举
package single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//enum 是一个什么? 本身也是一个class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
//不可以用反射破坏枚举的单例
class Test{
public static void main(String[]args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
EnumSingle instance1 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance2 = declaredConstructor.newInstance();
//NoSuchMethodException: single.EnumSingle.<init>()
System.out.println(instance1);
System.out.println(instance2);
}
}
枚举是有参构造,并且是两个参数

枚举类的最终反编译源码
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: EnumSingleton.java
package 53554F8B6A215F0F;
public final class EnumSingleton extends Enum
{
public static EnumSingleton[] values()
{
return (EnumSingleton[])$VALUES.clone();
}
public static EnumSingleton valueOf(String name)
{
return (EnumSingleton)Enum.valueOf(53554F8B6A215F0F/EnumSingleton,
name);
}
private EnumSingleton(String s, int i)
{
super(s, i);
}
public EnumSingleton getInstance()
{
return INSTANCE;
}
public static final EnumSingleton INSTANCE;
private static final EnumSingleton $VALUES[];
static
{
INSTANCE = new EnumSingleton("INSTANCE", 0);
$VALUES = (new EnumSingleton[] {
INSTANCE
});
}
}
浙公网安备 33010602011771号