博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之单例模式
阅读量:4660 次
发布时间:2019-06-09

本文共 2739 字,大约阅读时间需要 9 分钟。

        方法的提炼和重要,同样的代码加入出现了5遍,只要我们稍微一修改,我们要修改的就是5个地方,可能我们有时候改了几个地方,有1、2个地方漏改了,方法的提炼有助于开发的维护和扩展。好吧,扯远了,回到我们的正题,单例模式。
 
一、定义:
单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。
      通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你的实例化多个对象,一个最好的方法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
    通俗的说就是, 将构造函数声明为private,防止外部类的实例化,提供一个public的方法用于生成对象。
二、UML图
 
 
名词解释:
lazy Loading:延迟加载,即在需要的时候载加载类,而不是一开始就加载。
 
三、常用方法形式
方式1、将构造函数声明为private,提供一个公共的外界调用该对象的方式
(lazy Loading,线程不安全)
public class Singleton{private static Singletoninstance=null;private Singleton(){  //构造方法是private,堵死了外界用new实例化//dosomething}//获取本类实例的唯一全局访问点public static Singleton getInstance(){            if(instance==null){  //若实例不存在,创建一个返回,否则返回已有实例instance=new Singleton();}return instance;}}

 

  
主要缺点:在线程下工作容易出问题,生成多个对象。
 
方式2、(lazy Loading,线程不安全)
public class Singleton{private static Singletoninstance=null;private Singleton(){  //构造方法是private,堵死了外界用new实例化//dosomething}//获取本类实例的唯一全局访问点public static synchronized Singleton getInstance(){            if(instance==null){  //若实例不存在,创建一个返回,否则返回已有实例instance=new Singleton();}return instance;}}

  能很好的解决上面说的多线程问题,但是使多线程的变成了单线程的效率,效率很差。一般不适用。

 
方式3、在类里面生成唯一的对象,每次生成该对象都是返回那唯一的对象。
(非Lazy Loading)
public class Singleton{//在自己内部定义自己的一个实例,只供内部调用private static Singleton instance=new Singleton();private Singleton(){//dosomething}  //这里提供了一个供外部访问本class的静态方法,可以直接访问         public static Singleton getInstance(){  return instance;}}

 

  不是延迟加载类型,类在
类加载的时候就进行了初始化,这样子会浪费一定的知源,违背了延迟加载的性质。
 
方式4
  
public class Singleton{private static Singletoninstance=null;private Singleton(){//dosomething}public static Singleton getInstance(){if(instance==null){synchronized(Singleton.class){if(null==instance){instance=new Singleton();}}}return instance;}}//这个模式将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。

 

 
 通过静态代码块(static)的方式,将对象生成延迟了类初始化的时候。
 
方式5、双重锁机制
  public class Singleton  {  //定义一个私有的静态全局变量来保存该类的唯一实例  private static Singleton singleton;//定义一个只读静态对象  //且这个对象是在程序运行时创建的  private static readonly object syncObject = new object();///   /// 构造函数必须是私有的  /// 这样在外部便无法使用 new 来创建该类的实例  ///   private Singleton()  {}///   /// 定义一个全局访问点  /// 设置为静态方法  /// 则在类的外部便无需实例化就可以调用该方法  ///   /// 
  public static Singleton GetInstance()  {  //这里可以保证只实例化一次  //即在第一次调用时实例化  //以后调用便不会再实例化//第一重 singleton == null  if (singleton == null)  {lock (syncObject)  {  //第二重 singleton == null  if (singleton == null)  {  singleton = new Singleton();  }  }  }  return singleton;  }  }  
解析:在外层已经判断了 singleton == null
为什么在lock()后面还需要判断一次
singleton == null呢? 
    因为,加入有两个线程同时调用了getInstance()方法,它们将都可以通过第一重singleton == null的判断,然后由于lock机智,这两个线程则一个进入,另一个在排队等待,必须要其中的一个进入并出来后,另外一个才能进入,因此如果没有了第二重instance是否为空的判断,则第一个线程创建了实例,而第二个线程还是可以继续再创建新的实例,这就没有达到单例的目的了。
 
 
 
 
 
 
 

转载于:https://www.cnblogs.com/0201zcr/p/4617027.html

你可能感兴趣的文章
关于jedis2.4以上版本的连接池配置,及工具类
查看>>
记忆讲师石伟华微信公众号2017所有文章汇总(待更新)
查看>>
FactoryBean
查看>>
Coolite动态加载CheckboxGroup,无法在后台中获取
查看>>
C3P0连接池工具类使用
查看>>
SVN常用命令备注
查看>>
孩子教育
查看>>
解决Cacti监控图像断断续续问题
查看>>
结构体的传参理解成员的存储方式
查看>>
python 进程与线程(理论部分)
查看>>
什么是API
查看>>
强名称程序集(strong name assembly)——为程序集赋予强名称
查看>>
1028. List Sorting (25)
查看>>
BZOJ 1613: [Usaco2007 Jan]Running贝茜的晨练计划
查看>>
ubuntu 重启命令,ubuntu 重启网卡方法
查看>>
Linux的学习:
查看>>
JavaScript中的原型继承原理
查看>>
Python logger模块
查看>>
jquery控制css的display(控制元素的显示与隐藏)
查看>>
关于python做人工智能的一个网页(很牛逼)
查看>>