• 设计模式-单例模式


    1、单例模式的简介

    定义:属于创建型模式,一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象

    目标:保证一个类仅有一个实例,并提供一个访问它的全局访问点

    解决问题:一个类被频繁的创建和销毁

    说明:单例类只能有一个实例,必须自己创建自己的唯一实例,必须给所有其他对象提供这一实例

    2、懒汉式,线程不安全

    定义:最基本最简单的单例模式实现方式,使用实例的时候才会去初始化

    优点:简单

    缺点:线程不安全,不适合多线程

    实现:

    //单例类
    public class lazyA {
        private static lazyA lazya;
        /**
         * 为了规范,添加空白的构造函数
         */
        public lazyA(){
    
        }
        public static lazyA getName (){
            if(lazya == null){
                lazya = new lazyA();
                System.out.println("This is a new lazyA");
            }else{
                System.out.println("This is exist a lazyA");
            }
            return lazya;
        }
        public void show(){
            System.out.println("How are you");
        }
    }
    
    //测试方法
     public static void main(String[] args) {
            lazyA lazyA1 = design.single.lazyA.getName();
            lazyA1.show();
            System.out.println("========================");
            lazyA lazyA2 = design.single.lazyA.getName();
            lazyA2.show();
            System.out.println("========================");
            System.out.println(lazyA1==lazyA2);
        }
    //测试结果
    This is a new lazyA
    How are you
    ========================
    This is exist a lazyA
    How are you
    ========================
    true

    3、懒汉式,线程安全

    定义:最基本最简单的单例模式实现方式,使用实例的时候才会去初始化,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步

    优点:第一次调用才初始化,避免内存浪费

    缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率

    实现:

    //单例类
    public class lazyB {
        private static lazyB lazya;
        /**
         * 为了规范,添加空白的构造函数
         */
        public lazyB(){
    
        }
        public static synchronized lazyB getName (){
            if(lazya == null){
                lazya = new lazyB();
                System.out.println("This is a new lazyB");
            }else{
                System.out.println("This is exist a lazyB");
            }
            return lazya;
        }
        public void show(){
            System.out.println("How are you");
        }
    }
    
    //测试方法
     public static void main(String[] args) {
            lazyB lazyB1 = design.single.lazyB.getName();
            lazyB1.show();
            System.out.println("========================");
            lazyB lazyB2 = design.single.lazyB.getName();
            lazyB2.show();
            System.out.println("========================");
            System.out.println(lazyB1==lazyB2);
        }
    //测试结果
    This is a new lazyB
    How are you
    ========================
    This is exist a lazyB
    How are you
    ========================
    true

    4、饿汉式

    定义:这种方式比较常用,但容易产生垃圾对象,类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了

    优点:线程安全,没有锁,效率高

    缺点:类加载时就初始化,浪费内存

    实现:

    //单例类
    public class hungry {
        public static hungry hungry = new hungry();
        private hungry(){
            System.out.println("very hungry");
        }
        public static hungry getHungry(){
            System.out.println("me too");
            return hungry;
        }
        public void show(){
            System.out.println("hungry show");
        }
    }
    
    //测试方法
     public static void main(String[] args) {
            hungry hungry1 = design.single.hungry.getHungry();
            hungry1.show();
            System.out.println("===============================");
            hungry hungry2 = design.single.hungry.getHungry();
            hungry2.show();
            System.out.println("========================");
            System.out.println(hungry1==hungry2);
        }
    //测试结果
    very hungry
    me too
    hungry show
    ===============================
    me too
    hungry show
    ========================
    true

    5、枚举

    定义:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法 它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化

    优点:简单,容易实现,支持多线程

    缺点:JDK1.5后加入的enum特性,不能通过 reflection attack 来调用私有构造方法

    实现:

    //单例类
    public class enumTest {
        private enumTest() {
    
        }
    
        static enum singleEnum {
            //创建一个枚举对象,该对象为单例
            SINGLE_ENUM;
            private  enumTest enumTest;
    
            private singleEnum() {
                System.out.println("this is a enum");
                enumTest = new enumTest();
            }
            public enumTest getEnumTest(){
                System.out.println("get enumEnum");
                return enumTest;
            }
        }
        public  static enumTest getInstance(){
            System.out.println("this is a enumTest");
            return singleEnum.SINGLE_ENUM.getEnumTest();
        }
    }
    
    //测试方法
     public static void main(String[] args) {
           enumTest enumTest1 = enumTest.getInstance();
            System.out.println("========================");
            enumTest enumTest2 = enumTest.getInstance();
            System.out.println("========================");
            System.out.println(enumTest1==enumTest2);
        }
    //测试结果
    this is a enumTest
    this is a enum
    get enumEnum
    ========================
    this is a enumTest
    get enumEnum
    ========================
    true

    6、双检锁(DCL)

    定义:这种方式采用双锁机制,安全且在多线程情况下能保持高性能

    优点:性能高

    缺点:实现复杂

    实现:

    //单例类
    public class Dcl {
        private static volatile Dcl dcl = null;
        private Dcl(){
    
        }
        public static Dcl getDcl(){
            System.out.println(dcl);
            System.out.println("one:"+(dcl == null));
            if(dcl == null){
                synchronized (Dcl.class) {
                    if (dcl == null) {
                        dcl = new Dcl();
                    }
                    System.out.println("two:"+(dcl == null));
                }
            }
            return dcl;
        }
    }
    
    //测试方法
    public  class Test {
        public static void main(String[] args) {
            Dcl dcl1 = Dcl.getDcl();
            System.out.println("===============================");
            Dcl dcl2 = Dcl.getDcl();
            System.out.println("========================");
            System.out.println(dcl1==dcl2);
        }
    }
    //测试结果
    null
    one:true
    two:false
    ===============================
    design.single.Dcl@4554617c
    one:false
    ========================
    true

    7、静态内部类

    定义:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用

    实现:

    //单例类
    
    public class StaticTest {
        private static final StaticTest STATIC_TEST = new StaticTest();
        private StaticTest(){
            System.out.println("one StaticTest");
        }
        public static  final  StaticTest getStaticTest(){
            System.out.println("two StaticTest");
            return StaticTest.STATIC_TEST;
        }
    }
    
    //测试方法
     public static void main(String[] args) {
            StaticTest staticTest1 = StaticTest.getStaticTest();
            System.out.println("==============================");
            StaticTest staticTest2 = StaticTest.getStaticTest();
            System.out.println("==============================");
            System.out.println(staticTest1==staticTest2);
    
        }
    //测试结果
    one StaticTest
    two StaticTest
    ==============================
    two StaticTest
    ==============================
    true
  • 相关阅读:
    49. Group Anagrams
    43. Multiply Strings
    22. Generate Parentheses
    17. Letter Combinations of a Phone Number
    8. String to Integer (atoi)
    【转】C#中base关键字的几种用法:base()
    【转】C#中virtual和abstract的区别
    [转]C#中的abstract 类和方法
    【转】C#虚方法virtual详解
    【转】C#中protected用法详解
  • 原文地址:https://www.cnblogs.com/carblack/p/13747994.html
Copyright © 2020-2023  润新知