精华内容
下载资源
问答
  • 设计模式之单例设计模式

    万次阅读 多人点赞 2021-03-21 20:28:27
    JAVA一共有23种设计模式,我们今天首先来学其中一种:单例设计模式 2 单例设计模式 单例模式可以说是大多数开发人员在实际中使用最多的,常见的Spring默认创建的bean就是单例模式的。 单例模式有很多好处,比如可节约...

    1 设计模式(Design pattern)

    代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
    JAVA一共有23种设计模式,我们今天首先来学其中一种:单例设计模式
    23种设计模式

    2 单例设计模式

    单例模式可以说是大多数开发人员在实际中使用最多的,常见的Spring默认创建的bean就是单例模式的。
    单例模式有很多好处,比如可节约系统内存空间,控制资源的使用。
    其中单例模式最重要的是确保对象只有一个。
    简单来说,保证一个类在内存中的对象就一个。
    RunTime就是典型的单例设计,我们通过对RunTime类的分析,一窥究竟。

    3 RunTime单例设计源码剖析

     /**
     * Every Java application has a single instance of class
     * <code>Runtime</code> that allows the application to interface with
     * the environment in which the application is running. The current
     * runtime can be obtained from the <code>getRuntime</code> method.
     * <p>
     * An application cannot create its own instance of this class.
     *
     * @author  unascribed
     * @see     java.lang.Runtime#getRuntime()
     * @since   JDK1.0
     */
    public class Runtime {
    	//2.创建静态的全局唯一的对象
    	private static Runtime currentRuntime = new Runtime();
    
    	//1.私有化构造方法,不让外部来调用
        /** Don't let anyone else instantiate this class */
        private Runtime() {}
        
    	//3.通过自定义的静态方法获取实例
        public static Runtime getRuntime() {
            return currentRuntime;
    }
    }
    

    通过分析,底层的实现思路一共分为了3个步骤:

    • 对本类构造方法私有化,防止外部调用构造方法创建对象
    • 创建全局唯一的对象,也做私有化处理
    • 通过自定义的公共方法将创建好的对象返回(类似封装属性后的getXxx() )

    那我们不妨自己尝试着来写写单例模式

    4 练习:单例设计模式1-饿汉式实现方式

    创建包: cn.tedu.design
    创建类: Singleton1.java

    package cn.tedu.design;
    /*本类用于实现单例设计模式实现方案1:饿汉式*/
    public class Singleton1 {
        public static void main(String[] args) {
            //5.在main()中,不通过对象,直接通过类名,调用静态方法
            MySingle single1 = MySingle.getSingle();
            MySingle single2 = MySingle.getSingle();
            //6.用==检验是否是同一个对象
            System.out.println(single1 == single2);//true
            System.out.println(single1);
            System.out.println(single2);
        }
    }
    //0.创建自己的单例程序
    class MySingle{
        //1.提供构造方法,并将构造方法私有化
        /*1.构造方法私有化的目的:为了防止外界随意创建本类对象*/
        private MySingle(){ }
    
        //2.创建本类对象,并将对象也私有化
        //4.2由于静态资源只能调用静态资源,所以single对象也需要设置成静态
        private static MySingle single = new MySingle();
    
        //3.提供公共的访问方式,返回创建好的对象
        //4.1为了不通过对象,直接调用本方法,需要将本方法设置为静态
        public static MySingle getSingle(){
            return single;
        }
    }
    

    2.4 单例设计模式2-懒汉式实现方式
    创建包: cn.tedu.design
    创建类: Singleton2.java

    package cn.tedu.design;
    /*本类用于实现单例设计模式优化实现方案2:懒汉式
    * 关于单例设计模式的两种实现方式:
    * 1.饿汉式:不管你用不用这个类的对象,都会直接先创建一个
    * 2.懒汉式:先不给创建这个类的对象,等你需要的时候再创建--延迟加载的思想
    * 延迟加载的思想:是指不会在第一时间就把对象创建好占用内存
    *               而是什么时候用到,什么时候再去创建对象
    * 3.线程安全问题:由于我们存在唯一的对象single2,并且多条语句都操作了这个变量
    *   如果将程序放到多线程的环境下,就容易出现数据安全的问题,所以解决方案:
    *   1) 将3条语句都使用同步代码块包裹,保证同步排队的效果
    *   2) 由于getSingle2()只有这3条语句,所以也可以将本方法设置为同步方法*/
    public class Singleton2 {
        public static void main(String[] args) {
            //5.调用方法查看结果
            MySingle2 single1 = MySingle2.getSingle2();
            MySingle2 single2 = MySingle2.getSingle2();
            System.out.println(single1 == single2);
            System.out.println(single1);
            System.out.println(single2);
        }
    }
    //0.创建自己的单例程序
    class MySingle2{
        //6.2创建一个静态的唯一的锁对象
        static Object o = new Object();
        //1.私有化本类的构造方法
        private MySingle2(){ }
        //2.创建的是本类对象的引用类型变量,用来保存对象的地址值,默认值是null
        private static MySingle2 single2 ;
        //3.提供公共的get方法
        synchronized public static MySingle2 getSingle2(){
            //4.判断之前是否创建过对象,之前创建过就直接走return
            //之前如果没有创建过,才走if,创建对象并将对象返回
            //6.有共享数据+多条语句操作数据,所以尽量提前处理,避免多线程数据安全隐患
            //6.1 解决方案1:加同步代码块
            //6.2 解决方案2:将本方法getSingle2()设置为同步方法
            //因为这个方法里所有的语句都需要同步
            synchronized (o) {//静态方法中使用的锁对象也得是静态的
                if (single2 == null) {//single2还是默认值,说明之前没有创建过对象
                    single2 = new MySingle2();//没创建过才创建,并赋值给single2
                }
                return single2;
            }
        }
    }
    

    单例设计模式到这里就结束啦,后续我们还可以继续学习下其他的设计模式哦~

    下一节 注解 点这里哦

    展开全文
  • C++ 单例设计模式屏幕练习.pdf
  • JAVA设计模式单例模式

    万次阅读 多人点赞 2014-04-16 06:51:34
    本文继续介绍23种设计模式系列之单例模式。 概念:  java中单例模式是一种常见的设计模式单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类...

    本文继续介绍23种设计模式系列之单例模式。

    概念:
      java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
      单例模式有以下特点:
      1、单例类只能有一个实例。
      2、单例类必须自己创建自己的唯一实例。
      3、单例类必须给所有其他对象提供这一实例。
      单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。


    一、懒汉式单例

     

    //懒汉式单例类.在第一次调用的时候实例化自己 
    public class Singleton {
        private Singleton() {}
        private static Singleton single=null;
        //静态工厂方法 
        public static Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
        }
    }

     

    Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

    (事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

    但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题:

     

    1、在getInstance方法上加同步

     

    public static synchronized Singleton getInstance() {
             if (single == null) {  
                 single = new Singleton();
             }  
            return single;
    }

     

     

     

    2、双重检查锁定

     

    public static Singleton getInstance() {
            if (singleton == null) {  
                synchronized (Singleton.class) {  
                   if (singleton == null) {  
                      singleton = new Singleton(); 
                   }  
                }  
            }  
            return singleton; 
        }

     

    3、静态内部类

     

    public class Singleton {  
        private static class LazyHolder {  
           private static final Singleton INSTANCE = new Singleton();  
        }  
        private Singleton (){}  
        public static final Singleton getInstance() {  
           return LazyHolder.INSTANCE;  
        }  
    }  

    这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。

     

     

     

     

     

     

    二、饿汉式单例

     

    //饿汉式单例类.在类初始化时,已经自行实例化 
    public class Singleton1 {
        private Singleton1() {}
        private static final Singleton1 single = new Singleton1();
        //静态工厂方法 
        public static Singleton1 getInstance() {
            return single;
        }
    }

    饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

     

     

     

     

    三、登记式单例(可忽略)

    //类似Spring里面的方法,将类名注册,下次从里面直接获取。
    public class Singleton3 {
        private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
        static{
            Singleton3 single = new Singleton3();
            map.put(single.getClass().getName(), single);
        }
        //保护的默认构造子
        protected Singleton3(){}
        //静态工厂方法,返还此类惟一的实例
        public static Singleton3 getInstance(String name) {
            if(name == null) {
                name = Singleton3.class.getName();
                System.out.println("name == null"+"--->name="+name);
            }
            if(map.get(name) == null) {
                try {
                    map.put(name, (Singleton3) Class.forName(name).newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            return map.get(name);
        }
        //一个示意性的商业方法
        public String about() {    
            return "Hello, I am RegSingleton.";    
        }    
        public static void main(String[] args) {
            Singleton3 single3 = Singleton3.getInstance(null);
            System.out.println(single3.about());
        }
    }

     登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。 

    这里我对登记式单例标记了可忽略,我的理解来说,首先它用的比较少,另外其实内部实现还是用的饿汉式单例,因为其中的static方法块,它的单例在类被装载的时候就被实例化了。

     

    饿汉式和懒汉式区别

    从名字上来说,饿汉和懒汉,

    饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,

    而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。

    另外从以下两点再区分以下这两种方式:

     

    1、线程安全:

    饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

    懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。


     

    2、资源加载和性能:

    饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,

    而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

    至于1、2、3这三种实现又有些区别,

    第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,

    第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗

    第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。

     

    什么是线程安全?

    如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

    或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

     

    应用

    以下是一个单例类使用的例子,以懒汉式为例,这里为了保证线程安全,使用了双重检查锁定的方式:

     

    public class TestSingleton {
    	String name = null;
    
            private TestSingleton() {
    	}
    
    	private static volatile TestSingleton instance = null;
    
    	public static TestSingleton getInstance() {
               if (instance == null) {  
                 synchronized (TestSingleton.class) {  
                    if (instance == null) {  
                       instance = new TestSingleton(); 
                    }  
                 }  
               } 
               return instance;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public void printInfo() {
    		System.out.println("the name is " + name);
    	}
    
    }

    可以看到里面加了volatile关键字来声明单例对象,既然synchronized已经起到了多线程下原子性、有序性、可见性的作用,为什么还要加volatile呢,原因已经在下面评论中提到,

    还有疑问可参考http://www.iteye.com/topic/652440
    和http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

     

     

     

    public class TMain {
    	public static void main(String[] args){
    		TestStream ts1 = TestSingleton.getInstance();
    		ts1.setName("jason");
    		TestStream ts2 = TestSingleton.getInstance();
    		ts2.setName("0539");
    		
    		ts1.printInfo();
    		ts2.printInfo();
    		
    		if(ts1 == ts2){
    			System.out.println("创建的是同一个实例");
    		}else{
    			System.out.println("创建的不是同一个实例");
    		}
    	}
    }
    

     运行结果:

    结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。

    对于单例模式的几种实现方式,知道饿汉式和懒汉式的区别,线程安全,资源加载的时机,还有懒汉式为了实现线程安全的3种方式的细微差别。

    更多设计模式:23种设计模式系列

    作者:jason0539

    博客:http://blog.csdn.net/jason0539(转载请说明出处)

    展开全文
  • 单例设计模式

    2019-10-12 20:54:14
    单例设计模式单例设计模式 单例设计模式 作用:在应用程序中有保证最多只能有一个实例 好处: 提升运行效率 实现数据共享比如:application对象,其在四大作用域共享 懒汉式 单例设计模式: 第一步:构造...

    单例设计模式

    单例设计模式

    1. 作用:在应用程序中有保证最多只能有一个实例
    2. 好处:
      提升运行效率
      实现数据共享比如:application对象,其在四大作用域共享
    3. 懒汉式
      为什么叫懒汉式:因为对象只有被调用的时候才会被创建
      单例设计模式:
      第一步:构造方法私有化,那么其他类就不可以实例化这个对象,
    public class SingleTon {
        //由于对象需要被静态方法调用,所以对象设置为static
        //由于对象是static,必须把设置访问权限修饰符改为private,如果是public的话,不经过访问入口
        private static SingleTon singleTon;
        private SingleTon(){} //设置成私有化的时候需要对外提供一个访问入口
        //实例方法必须通过对象调用,此时不可以,所以将方法设置为静态方法
        public static SingleTon getInstance(){
            //添加逻辑 如果实例化过,直接返回
            if (singleTon == null){
                /**
                 * 多线程访问下,可能出现if同时成立的情况,添加锁
                 */
                synchronized (SingleTon.class){
                    if (singleTon == null){
                        singleTon = new SingleTon();
                    }
                }
            }
            return singleTon;
        }
    }
    
    

    由于添加了锁,所以导致了效率的降低
    4. 饿汗式
    解决了多线程访问可能出现同一个对象和效率低的问题

    public class NewSingleTon {
        //为了避免锁的冲突以及效率问题,在类加载的时候进行实例化
        private static NewSingleTon newSingleTon = new NewSingleTon();
        private NewSingleTon(){}
        public static NewSingleTon getInstance(){
            return newSingleTon;
        }
    }
    
    
    1. 测试类
    public class Test {
        public static void main(String[] args) {
            SingleTon singleTon = SingleTon.getInstance();
            SingleTon singleTon1 = SingleTon.getInstance();
            System.out.println(singleTon == singleTon1);
    
        }
    }
    
    展开全文
  • java单例设计模式

    2016-07-31 22:32:12
    java单例设计模式
  • [设计模式]单例设计模式

    千次阅读 2020-04-14 20:39:47
    单例设计模式 单例设计模式是指某个只能生成一个实例(对象),该提供了一个全局访问点供外部获取该实例. 可以拓展为有限多例模式 代码展示 ...

    github地址:https://github.com/1711680493

    点我进入github

    如需了解更多设计模式,请进入我的设计模式专栏

    单例设计模式

    单例设计模式是指某个类只能生成一个实例(对象),该类提供了一个全局访问点供外部获取该实例.

    可以拓展为有限多例模式 

    单例模式展示

    /**
     * 单例设计模式
     * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
     * @version 1.0
     */
    public class SingleMode {
    	/**
    	 * 此类唯一的对象
    	 */
    	private static SingleMode single = new SingleMode();
    	/**
    	 * 构造私有 别的类无法创建此类对象
    	 */
    	private SingleMode() {}
    	
    	/**
    	 * 将唯一的对象通过某种方法提供出去 供外界使用
    	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
    	 * @return
    	 */
    	public static SingleMode getSingle() {
    		return single;
    	}
    }

    实例展示

    在Windows操作系统中,系统自带的东西大部分都是单例模式的,比如回收站,任务管理器,资源管理器等.

    例子:创建一个ShendiPerson类,拥有Money的属性,使用单例模式来获取/更改参数

    /**
     * 单例模式测试类
     * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
     * @version 1.0
     */
    public class SingleModeTest {
    	public static void main(String[] args) {
    		//获取唯一的对象
    		ShendiPerson shendi1 = ShendiPerson.getShendi();
    		//在获取一次 验证效果
    		ShendiPerson shendi2 = ShendiPerson.getShendi();
    		//现在的money是为0的 初始值 我们设置shendi1的money
    		shendi1.setMoney(666666666);
    		//输出看一下结果
    		System.out.println("shendi1 设置了money: " + shendi1.getMoeny());
    		//shendi2我们是没有设置money的 获取看一下数值
    		System.out.println("shendi2 没有设置money: " + shendi2.getMoeny());
    	}
    }
    
    class ShendiPerson {
    	/**
    	 * 创建此类唯一的对象
    	 */
    	private static final ShendiPerson SHENDI = new ShendiPerson();
    	private ShendiPerson() {};
    	
    	/**
    	 * 钱
    	 */
    	private int money;
    	
    	/**
    	 * 设置钱的方法
    	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
    	 * @param money
    	 */
    	public void setMoney(int money) { this.money = money; }
    	/**
    	 * 钱是私有的,提供的获取钱的方法
    	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
    	 * @return
    	 */
    	public int getMoeny() { return money; }
    	
    	/**
    	 * 返回唯一对象的方法
    	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
    	 * @return
    	 */
    	public static ShendiPerson getShendi() {
    		return SHENDI;
    	}
    }

    结果:

    展开全文
  • python设计模式之单例设计模式

    千次阅读 2017-10-21 20:05:50
    一、理解单例设计模式 二、单例设计模式中的懒汉式实例化 三、模块级别的单例模式 四、Monostate单例模式 五、单例和元 六、单利模式I 七、单例模式II 八、单例模式的缺点
  • 简述单例设计模式

    2019-04-26 16:14:13
    单例设计模式(singleton):将限制为单一的实例,保证一个在内存中只有一个对象。 单例设计模式的步骤: 饿汉单例设计模式 1. 私有化构造函数。 2. 声明本的引用类型变量,并且使用该变量指向本对象。 ...
  • Java 单例设计模式

    2020-10-28 11:49:45
    单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个只能存在一个对象实例,并且该只提供一个取得其对象实例的方法。 二、如何应用单例设计模式 根据定义,一个只能存在一种对象实例,所以我们需...
  • java使用枚举、饿汉式、懒汉式、内部实现单例设计模式 可以说我到现在都没有使用上(在实际公司工作中),为什么会这样呢,我们来看看单例设计模式有哪些常见的应用场景 window 的控制面板、任务管理器、回收站 ...
  • Java设计模式——单例设计模式

    千次阅读 2018-05-25 10:13:31
    我们一般在学习的第一个设计模式都是单例设计模式,因为单例设计模式广泛的应用在我们程序开发中。今天就和大家简单的聊一聊单例设计模式,因为在我们刚开始学习Java基础时,就了解了单例,有的同学在学习时非常困惑...
  • 内部创建对象实例 private final static Singleton instance = new Singleton(); //3. 提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
  • 单例模式,属于创建型模式,《设计模式》一书对它做了定义:保证一个仅有一个实例,并提供一个全局访问点。 单例模式适用于无状态的工具、全局信息等场景。例如日志工具,在系统中记录日志;假设我们需要...
  • 浅谈java单例设计模式

    2021-01-21 16:45:47
    所谓单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个只能存在一个对象实例,并且该只提供一个取得其对象实例的方法。 如果我们要让在一个虚拟机中只能产生一个对象: 将的构造器的访问...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 168,306
精华内容 67,322
关键字:

属于单例设计模式的类