网站地图 | RSS订阅 老铁博客 - 上海SEO优化|上海网站建设|蜘蛛池出租|站群代搭建
你的位置:首页 » 前端脚本 » 正文

单例,单例模式

2020-4-25 13:55:38 | 作者:老铁SEO | 0个评论 | 人浏览

  单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。


  通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。


  单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。


  要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。


  使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。


  一、实例控制


  单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。


  二、灵活性


  因为类控制了实例化过程,所以类可以灵活更改实例化过程。


  一、开销


  虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。


  二、可能的开发混淆


  使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。


  三、对象生存期


  不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NETFramework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。


  单例模式


  单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。


  通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。


  单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。


  要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。


  使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。


  一、实例控制


  单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。


  二、灵活性


  因为类控制了实例化过程,所以类可以灵活更改实例化过程。


  一、开销


  虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。


  二、可能的开发混淆


  使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。


  三、对象生存期


  不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NETFramework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。


  单例模式懒汉和饿汉


  1、饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。


  2、从实现方式来讲他们最大的区别就是懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,饿汉式无需关注多线程问题,写法简单明了,能用则用。真正用到的时候才去建这个单例对象,“饿汉式”是在不管用不用得上,一开始就建立这个单例对象。


  1、单件模式用途:单件模式属于工厂模式的特例,只是它不需要输入参数并且始终返回同一对象的引用。单件模式能够保证某一类型对象在系统中的唯一性,即某类在系统中只有一个实例。


  2、它的用途十分广泛,打个比方,我们开发了一个简单的留言板,用户的每一次留言都要将留言信息写入到数据库中,最直观的方法是没次写入都建立一个数据库的链接。


  3、这是个简单的方法,在不考虑并发的时候这也是个不错的选择。但实际上,一个网站是并发的,并且有可能是存在大量并发操作的。如果我们对每次写入都创建一个数据库连接,那么很容易的系统会出现瓶颈,系统的精力将会很多的放在维护链接上而非直接查询操作上。这显然是不可取的。


  单例模式应用场景


  单例模式要点三:


  某类能实例;


  二必须自行创建实例;


  三必须自行向整系统提供实例


  复制代码代码:


  /*单例模式举例,其要点:


  *


  *1.$_instance必须声明静态私变量


  *2.构造函数克隆函数必须声明私,防止外部程序new类失单例模式意义


  *3.getInstance()必须声明公,必须调用返唯实例引用


  *4.::操作符能访问静态变量或静态函数


  *5.PHP单例模式相言,PHP解释运行机制使每PHP页面解释执行所相关资源都收


  *说PHP语言级别没办让某象驻内存PHP所变量都页面级论全局变量


  *类静态员都页面执行完毕清空,结重新建立新象完全失Singleton意义


  *,实际应用同页面能存业务逻辑,单例模式起重要作用,效避免重复


  *new象(注:new象消耗内存资源)行,所我说PHP单例模式相言


  *


  */


  classPeople


  {


  staticprivate$_instance=NULL;


  public$height='';


  public$age='';


  privatefunction__construct()


  {


  $this->height='185';


  $this->age=25;


  }


  privatefunction__clone()


  {


  //dosomething


  }


  staticpublicfunctiongetInstance()


  {


  if(!self::$_instanceinstanceofself)


  {


  //echo'lgh-big';


  self::$_instance=newself;


  }


  else


  {


  //fortestingonly


  //echo'gdc-xiaoairener';


  }


  returnself::$_instance;


  }


  publicfunctiongetHeight()


  {


  echo$this->height;


  }


  publicfunctiongetAge()


  {


  echo$this->age;


  }


  }


  functiontestInstance()


  {


  People::getInstance()->getAge();


  }


  //begintousetheclass


  $lgh=People::getInstance();


  $lgh->getHeight();


  echo'


  ';


  testInstance();


  ?>


  优点:单例模式避免量new操作每new操作都消耗内存资源系统资源


  缺点:PHP所变量论全局变量类静态员都页面级每页面执行都重新建立新象都页面执行完毕清空似乎PHP单例模式没意义所PHP单例模式我觉针单页面级请求现应用场景并需要共享同象资源非意义


  Why–要使用PHP单例模式


  PHP主要应用场合应用程序与数据库打交道应用场景所应用存量数据库操作比数据库句柄连接数据库行使用单例模式避免量new操作每new操作都消耗内存资源系统资源


  些抽象给代码片段


  使用传统式编码


  复制代码代码:


  ......


  //初始化数据库句柄


  $db=newDB(...);


  //比应用场景添加条用户信息:


  $db->addUserInfo();


  ......


  //我另外能要查找用户信息情景现函数要用数据库句柄资源我能需要做


  ......


  functiontest(){


  ......


  //我重新初始化数据库句柄,试想应用场景代码怕啊


  $db=newDB(...);


  $db->getUserInfo();


  ......


  //些朋友或许说我做啊我直接利用global关键字确global解决问题起单例模式作用OOP我拒绝编写代码global存安全隐患请参考相关书籍同单例模式恰恰全局变量种改进避免些存储唯实例全局变量污染命名空间


  global$db;//OOP我提倡编写代码


  ......


  }


  使用单例模式编码


  复制代码代码:


  ......


  //所应用情景数据库句柄资源嘿嘿效率高


  //资源节省代码简洁明:)


  DB::getInstance()->addUserInfo();


  DB::getInstance()->getUserInfo();


  ......


  How–何编写PHP单例模式


  解单例模式应用场景面我通编写单例模式具体实现代码掌握PHP单例模式核要点代码:


  复制代码代码:


  /**


  *PHP单例模式演示举例


  *@authorguohua.li


  *@modify2010-07-11


  *@website


  */


  classUser{


  /**


  *静态品变量保存全局实例


  *@accessprivate


  */


  staticprivate$_instance=NULL;


  /**


  *私化构造函数防止外界实例化象


  */


  privatefunction__construct(){}


  /**


  *私化克隆函数防止外界克隆象


  */


  privatefunction__clone(){}


  /**


  *静态,单例统访问入口


  *@returnobject返象唯实例


  */


  staticpublicfunctiongetInstance(){


  if(is_null(self::$_instance)||!isset(self::$_instance)){


  self::$_instance=newself();


  }


  returnself::$_instance;


  }


  /**


  *测试:获取用户名字


  */


  publicfunctiongetName(){


  echo'helloliguohua!';


  }


  }


  代码我总结PHP单例模式实现核要点三条:


  1.需要保存类唯实例静态员变量(通$_instance私变量)


  2.构造函数克隆函数必须声明私防止外部程序new类失单例模式意义


  3.必须提供访问实例公共静态(通getInstance)返唯实例引用


  PHP单例模式缺点


  众所周知PHP语言种解释型脚本语言种运行机制使每PHP页面解释执行所相关资源都收说PHP语言级别没办让某象驻内存asp、Java等编译型同比Java单例直存于整应用程序命周期变量跨页面级真做实例应用程序命周期唯性PHP所变量论全局变量类静态员都页面级每页面执行都重新建立新象都页面执行完毕清空似乎PHP单例模式没意义所PHP单例模式我觉针单页面级请求现应用场景并需要共享同象资源非意义


  单例模式线程安全


  哦哦,忽略我刚才的评论,你的问题是在不是同一个对象是不是就不安全了.这个问题也不尽然啊,要具体的看这个对象干啥事.如果你刚才说的那个计时器,如果加上单例模式,就安全了.如果不加上单例模式,不安全的原因是:


  servicecount++


  这语句实际上是执行了三个步骤,


  1从内存中读取servicecount的值,


  2servicecount加上1


  3将servicecount保存到内存.


  如果第一个线程还没有把加一之后的servicecount值保存到内存,这时候第二个线程进来,读取的值,也是第一线程读取的值,这时候就出问题.


  如果这个方法,能够用syncronized修饰,那么无论几个线程进来,都没有问题了.就没有必要进行单例了.所以你的处理办法是


  syncronized{


  servicecount++;


  }


  而不是用单例.


  结论:单例能够保证获取的类的实例只有一个,这时候是安全的.


  是否选择单例,跟具体业务有关系


  不是单例模式,也不一定就是不线程安全的(这是废话)

  • 本文来自: 老铁博客,转载请保留出处!欢迎发表您的评论
  • 相关标签:
  • 已有0位网友发表了一针见血的评论,你还等什么?

    必填

    选填

    记住我,下次回复时不用重新输入个人信息

    必填,不填不让过哦,嘻嘻。

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    相关推荐