zoukankan      html  css  js  c++  java
  • Item 3 ------单例模式的几种实现方式,及优缺点

    单例模式,是指一个类只有一个唯一的实例,一个类只会被实例化一次。实现这种效果,最佳的方式,编写包含单个元素的枚举类型。

    单例模式的最佳实现方式-----创建一个包含单个元素的枚举类

    public enum Elvis {
        ONE_INSTANCE;
    
        public void leaveTheBuilding() {
            System. out.println("Whoa baby, I'm outta here!" );
        }
    
    }
    
    ----------------------------------
    public class Test {
    
        public static void main(String[] args) {
            Elvis elvis = Elvis. ONE_INSTANCE;
            elvis.leaveTheBuilding();
        }
    }
    
    优点就是:无偿提供了序列化机制,绝对防止多次实例化,解决每次反序列化一个实例化时,再次创建一个心的实例的问题;并且处理了发射攻击(用户通过反射机制,调用了私有构造器,从而打破只有一个实例的规定).
    缺点:Java 1.5开始才支持。
     
    通过一个公有的静态成员来实现--唯一的实例,是一个公有的静态成员
    public class Elvis {
        public static final Elvis INSTANCE = new Elvis();
    
        private Elvis() {
        }
    
        public void leaveTheBuilding() {
            System. out.println("Whoa baby, I'm outta here!" );
        }
    
        // This code would normally appear outside the class!
        public static void main(String[] args) {
            Elvis elvis = Elvis. INSTANCE;
            elvis.leaveTheBuilding();
        }
    }
    缺点:1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。
    优点:它的表现简洁明了。
     
    通过公有的静态工厂方法
     
    public class Elvis {
        private static final Elvis INSTANCE = new Elvis();
    
        private Elvis() {
        }
    
        public static Elvis getInstance() {
            return INSTANCE ;
        }
    
        public void leaveTheBuilding() {
            System. out.println("Whoa baby, I'm outta here!" );
        }
    
        // This code would normally appear outside the class!
        public static void main(String[] args) {
            Elvis elvis = Elvis. getInstance();
            elvis.leaveTheBuilding();
        }
    }
    
    优点:
    将API与实现隔绝开,客户端只管调用getInstance()方法,不管该方法是怎么实现的。如此,你就可以修改getInstance()的实现,而不用考虑客户端是怎么使用的。
    比如,它可以被修改为,并不是返回一个唯一的实例;或者修改为,每个线程有一个唯一的实例,在某个线程范围内,该类的实例是唯一的。
     
    缺点:
    1.存在反射攻击缺陷。要抵御反射攻击,就要记录创建实例的个数,使用一个静态的类成员来保存。当实例个数超过1时,发出异常。
    2.在序列化一个类时,要添加方法readResolve。添加该方法的目的是,避免每次在反序列化的时候创建一个新的实例。
    解决缺点2的做法:
    添加一个readResolve()方法。
    public class Elvis implements Serializable {
        /**
         *
         */
        private static final long serialVersionUID = 1L;
    
        public static final Elvis INSTANCE = new Elvis();
    
        private String one;
    
        private Elvis() {
        }
    
        public void leaveTheBuilding() {
            System. out.println("Whoa baby, I'm outta here!" );
        }
    
        private Object readResolve() {
            // Return the one true Elvis and let the garbage collector
            // take care of the Elvis impersonator.
            return INSTANCE ;
        }
    
        // This code would normally appear outside the class!
        public static void main(String[] args) {
            Elvis elvis = Elvis. INSTANCE;
            elvis.leaveTheBuilding();
        }
    }
    

      

     
  • 相关阅读:
    双十一脱单就靠它:创维小湃蓝牙音箱体验评测
    专注产品真正价值:iWALK真无线蓝牙耳机体验评测
    美好的童年伙伴:360 智能儿童手表 P1体验评测
    前端也要学系列:设计模式之装饰者模式
    前端也要学系列:设计模式之策略模式
    你不知道的Javascript:有趣的setTimeout
    接受”不完美“:分布式事务学习总结
    如何进行团队技术分享
    又是一年寒冬时
    mybatis ~ 批量更新(sql循环)update foreach
  • 原文地址:https://www.cnblogs.com/ttylinux/p/4355241.html
Copyright © 2011-2022 走看看