返回顶部
扩大
缩小

Yeap

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
});
}
}

  

posted on 2020-06-19 10:01  YP泡泡  阅读(165)  评论(0)    收藏  举报

导航