zoukankan      html  css  js  c++  java
  • 再战设计模式(一)之单例模式

    关于设计模式,之前已经看过很多很多了.但是每次到过了很久之后,在此回忆总是感觉有模糊的感觉.这次我要重新学习一下设计模式.并在这里做一个博客记录,以作为以后的备忘吧.大家看过如果有问题或者更好的方式,可以在评论留言

    这篇文章也是我写设计模式的开章.主要方式是看视频和看书,设计模式被人称为GOF23 主要就是国外有4个编程牛人编写的这23中设计模式.大家主要理解人家的思想.而不是死记硬背,这句话也是对我自己说的.

    设计模式的分类

    1.创建型模式:5种

    单例模式 工厂模式 抽象工厂模式 建造者模式 原型模式

    2.结构型模式 7种

    适配模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式

    3.行为模式:11 种

    模板方法模式 命令模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式 策略模式 职责链模式 访问者模式

    分类主要是为了方便记忆 突然想到了jdk 8 有 9个函数式接口 想回忆下

    单例模式的实现

    单例模式-饿汗模式

      饿汉模式顾名思义就是非常饿,直接吃.其实关于单例模式的总结就一句话,私有构造方法,提供外部获取实例的方法

      所以在类加载的时候对象已经创建好了.方法没有锁,调用效率高!

    /**
     * @Created by xiaodao
     */
    public class Sington01 {
    
        //类初始化时立即加载对象(没有延迟加载的优势),天然的线程安全
        private static Sington01 instance = new Sington01();
    
    
        private Sington01() {
        }
    
        public static Sington01 getInstance(){
            return instance;
        }
    }

    延时加载模式

    public class Sington02 {
    
        /***
         * 延时加载模式,在调用的时候,才会获取对像
         */
        private static Sington02 sington ;
    
        private Sington02() {
        }
    
        /**
         * 同步调用效率低
         * @return
         */
        public static Sington02 getInstance(){
            synchronized (Sington02.class){
                if(null == sington){
                    sington= new Sington02();
                }
                return sington;
            }
        }
    }

     双重检查 double-check单例模式

    /**
     * @Created by xiaodao
     * 双重检索模式
     */
    public class Sington03 {
    
        /***
         *
         */
        private static volatile  Sington03 sington ;
    
        private Sington03() {
        }
    
        /**
         *
         * @return
         */
        public static Sington03 getInstance(){
            if(sington !=null ){
    
            }else{
                synchronized (Sington03.class){
                    if(sington== null){
                        sington = new Sington03();
                    }
                }
            }
            return sington;
    
        }
    
        public static void main(String[] args) {
            Sington03 sington03 = getInstance();
            Sington03 sington04 = getInstance();
            System.out.println(sington03);
            System.out.println(sington04);
        }
    }

    静态内部类 延时加载模式

    /**
     * @Created by xiaodao
     * 
     */
    public class Sington04 {
    
        /***
         *
         */
        private static class Sington04Interior {
            private static Sington04 instance= new Sington04();
        };
    
        private Sington04() {
        }
    
        /**
         *
         * @return
         */
        public static Sington04 getInstance(){
            return Sington04Interior.instance;
        }
    
        public static void main(String[] args) {
            Sington04 sington03 = getInstance();
            Sington04 sington04 = getInstance();
            System.out.println(sington03);
            System.out.println(sington04);
        }
    }
    View Code

    加载类的时候外部没有static属性不会像恶汉模式一样立即加载对象

    只有getInstance才会加载静态内部类.是线程安全的

    兼备了并发高效和延迟加载的优势

    枚举方式实现单例模式

    /**
     * @Created by xiaodao
     *
     */
    public enum  Sington05 {
    
        /***
         * 定义一个枚举.代表singleton的一个实例
         */
        INSTANCE;
        public void singletonOperator(){
            //这个单例的功能处理
        }
    
        public static void main(String[] args) {
            Sington05 sington05 = Sington05.INSTANCE;
        }
    
    }

    枚举的单例,可以避免反射和反序列来破解,实现比较简单

     反射跳过单例

     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    
            //第一次调用.
    //        Sington06 instance = Sington06.getInstance();
    //        System.out.println(instance);
            Class<Sington06> aClass = (Class<Sington06>) Class.forName("com.xiaodao.jdk8.disign.sington.Sington06");
            //获取构造器
            //第二次调用.
            Constructor<Sington06> declaredConstructor = aClass.getDeclaredConstructor(null);
            declaredConstructor.setAccessible(true);
            Sington06 s2 = declaredConstructor.newInstance();
            Sington06 s1 = declaredConstructor.newInstance();
            System.out.println(s1);
            System.out.println(s2);
            //第三次.
            Sington06 instance = Sington06.getInstance();
            System.out.println(instance);
            Sington06 s3 = declaredConstructor.newInstance();
        }

    这种方式可以跳过单例模式,需要在单例模式里加一个判断.
    private Sington06() {
    if(sington !=null){
    throw new RuntimeException();
    }
    }
     

    平时我们写项目不需要这样的判断.但是如果是写个框架的话,可能需要严谨一点,但是这也是有漏洞的,如果你没有创建过一次单例,那么通过反射就是无数次调用,如果你创建了.那么就不能通过反射就创建了.

    反序列化破解与防止反序列破解

     Sington06 instance = Sington06.getInstance();
            System.out.println(instance);
    
            FileOutputStream out = new FileOutputStream("/Users/xuyuanfang/study/java视频/disgin/a.txt");
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
            objectOutputStream.writeObject(instance);
            out.close();
            objectOutputStream.close();
    
            //反序列化
    
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/xuyuanfang/study/java视频/disgin/a.txt"));
            Sington06 s3 = (Sington06) objectInputStream.readObject();
            System.out.println(s3);
    
    防止破解:
    
        /**
         * 反序列化 如果定义了readResolve方法 直接调用这个方法返回对象,不需要重新创建对象
         * @return
         */
        public Object readResolve() throws ObjectStreamException {
            return  sington;
        }

    效率对比

    恶汉模式,比懒汉方式在多线程环境下效率好点

    如何选用呢?

    如果对象占用资源少,不需要延时加载

    枚举比恶汉式比较好

    如果对象资源占用比较大的话.需要延时加载

    静态内部类好于懒汉式 

  • 相关阅读:
    java.lang.OutOfMemoryError: bitmap size exceeds VM budget
    安装 android apk 提示应用程序未安装
    android Dialog去掉标题栏 和边框
    sqlite 中判断插入还是修改 REPLACE
    JAVA unicode转换成中文
    android listview button和EditText
    activity 接回返回值
    ActivityGroup 单击meun键没反应
    android.os.NetworkOnMainThreadException 异常处理
    android EditText或AutoCompleteTextView setOnKey事件问题
  • 原文地址:https://www.cnblogs.com/bj-xiaodao/p/10801232.html
Copyright © 2011-2022 走看看