菜鸟之路-浅谈设计模式之单例设计模式

单例设计模式

定义:确保一个类仅仅有一个实例,并且自行实例化并向整个系统提供这个实例。



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

通过单例模式能够保证系统中一个类仅仅有一个实例并且该实例易于外界訪问,从而方便对实例个数的控制并节约系统资源。假设希望在系统中某个类的对象仅仅能存在一个,单例模式是最好的解决方式。



关于单例设计模式的动机

对于系统中的某些类来说。仅仅有一个实例非常重要,比如。一个系统中能够存在多个打印任务,可是仅仅能有一个正在工作的任务;一个系统仅仅能有一个窗体管理器或文件系统;一个系统仅仅能有一个计时工具或ID(序号)生成器。如在Windows中就仅仅能打开一个任务管理器。

假设不使用机制对窗体对象进行唯一化,将弹出多个窗体。假设这些窗体显示的内容全然一致,则是反复对象。浪费内存资源;假设这些窗体显示的内容不一致。则意味着在某一瞬间系统有多个状态,与实际不符。也会给用户带来误解,不知道哪一个才是真实的状态。

因此有时确保系统中某个对象的唯一性即一个类仅仅能有一个实例非常重要。
怎样保证一个类仅仅有一个实例而且这个实例易于被訪问呢?定义一个全局变量能够确保对象随时都能够被訪问。但不能防止我们实例化多个对象。

一个更好的解决的方法是让类自身负责保存它的唯一实例。这个类能够保证没有其它实例被创建。而且它能够提供一个訪问该实例的方法。

这就是单例模式的模式动机


关于单例设计模式的要点

单例模式的要点有三个。一是某个类仅仅能有一个实例。二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
从详细实现角度来说,就是下面三点:一是单例模式的类仅仅提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

Java实例:

当一个类的实例能够有且仅仅能够一个的时候就须要用到了。为什么仅仅须要有一个呢?有人说是为了节约内存。但这仅仅是单例模式带来的一个优点。仅仅有一个实例确实降低内存占用。但是我觉得这不是使用单例模式的理由。

我觉得使用单例模式的时机是当实例存在多个会引起程序逻辑错误的时候。比方类似有序的号码生成器这种东西。怎么能够同意一个应用上存在多个呢?



饿汉式单例

public class Singleton {  private static Singleton singleton = new Singleton();  private Singleton(){}  public static Singleton getInstance(){  return singleton;  }  
}

懒汉式单例

public class Singleton {  private static Singleton singleton;  private Singleton(){}  public static synchronized Singleton getInstance(){  if(singleton==null){  singleton = new Singleton();  }  return singleton;  }  
} 
可是这样的单例类型在多线程中是不安全。有可能会出现两个INSTANCE,为什么呢?
假设当唯一实例尚未创建时,有两个线程同一时候调用创建方法,那么它们同一时候没有检測到唯一实例的存在,从而同一时候各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决问题的办法是为指示类是否已经实例化的变量提供一个相互排斥锁(详见双重锁单例。尽管这样会减少效率)。

比較:
饿汉式是线程安全的,在类创建的同一时候就已经创建好一个静态的对象供系统使用,以后不在改变。
懒汉式适合单线程。多线程情况下假设在创建实例对象时不加上synchronized则会导致对对象的訪问不是线程安全的。
从实现方式来讲他们最大的差别就是懒汉式是延时载入, 
他是在须要的时候才创建对象,而饿汉式在载入类时创建实例。 
 饿汉式无需关注多线程问题、写法简单明了、能用则用。可是它是载入类时创建实例、所以假设是一个工厂模式、缓存了非常多实例、那么就得考虑效率问题,由于这个类一载入则把全部实例无论用不用一块创建。 懒汉式的长处是延时载入、缺点是应该用同步。

单例模式的长处:
在内存中仅仅有一个对象。节省内存空间。
避免频繁的创建销毁对象,能够提高性能。
避免对共享资源的多重占用。
能够全局訪问。




适用场景:

因为单例模式的以上长处,所以是编程中用的比較多的一种设计模式。

我总结了一下我所知道的适合使用单例模式的场景:
须要频繁实例化然后销毁的对象。
创建对象时耗时过多或者耗资源过多,但又经经常使用到的对象。


有状态的工具类对象。
频繁訪问数据库或文件的对象。
以及其它我没用过的全部要求仅仅有一个对象的场景。


单例模式注意事项:
仅仅能使用单例类提供的方法得到单例对象,不要使用反射。否则将会实例化一个新对象。


不要做断开单例类对象与类中静态引用的危急操作。
多线程使用单例使用共享资源时,注意线程安全问题。

双重锁形式单例(懒汉式进阶版。哈哈)

 public static class Singleton{private static Singleton instance=null;private Singleton(){//do something}public static Singleton getInstance(){if(instance==null){synchronized(Singleton.class){if(null==instance){instance=new Singleton();}}}return instance;}
}
(有些朋友搞不懂为什么要推断两次Instance==null,由于在多线程中第一次推断时可能有两个或者多个instance==null。那么在synchronized锁里第一个instance已经new出来了,第二个或者后面进入的假设不推断就会反复new对象出来,所以在里面多一层推断确保Instance实例仅仅有一个)
这样还是有一个缺点就是:就是在一个线程还未全然初始化该对象时,而那个变量已经显示为被初始化,那么其它线程可能去使用这个未被全然初始化的实例,造成系统的崩溃。

只是这个在java5以上能够安全执行。


第二种完美实现的实现既线程安全又延迟载入的模式(Initialization on demand holder)使用静态内部类  演示样例:

Public class Singleton{Private Singleton(){};Public static class Singleton1{Private static final Singleton instance = new Singleton();
}    Public static Singleton getInstance(){Return Singleton1.instance;
}
}

这样就能保证在第一次调用getInstance()方法时,才会去初始化instance实例,并且该实例被定义为static,仅仅会被初始化一次。(这样的方法是网上看的,我还未用过,以后能够试试。哈哈大笑)

此文由本人从网上浏览总结而出。如需转载,请注明出处,谢谢!





当一个类的实例能够有且仅仅能够一个的时候就须要用到了。为什么仅仅须要有一个呢?有人说是为了节约内存,但这仅仅是单例模式带来的一个优点。仅仅有一个实例确实降低内存占用,但是我觉得这不是使用单例模式的理由。我觉得使用单例模式的时机是当实例存在多个会引起程序逻辑错误的时候。比方类似有序的号码生成器这种东西,怎么能够同意一个应用上存在多个呢?

转载于:https://www.cnblogs.com/yfceshi/p/7061055.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/371886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 32bit数据结构_python实现bitmap数据结构详解

bitmap是很常见的算法设计,例如用以Bloom Filter中;用以无反复整数金额的排列这些。bitmap一般根据数组来完成,数组中每一个原素能够当做是一系列二进制数,全部元素组成更高的二进制结合。针对Python而言,整数金额种类…

MVC如何使用开源分页插件shenniu.pager.js

最近比较忙,前期忙公司手机端接口项目,各种开发调试发布现在几乎上线无问题了;虽然公司项目忙不过在期间抽空做了两件个人觉得有意义的事情,一者使用aspnetcore开发了个人线上项目(要说线上其实只能ip访问,…

四. 基于环视Camera的BEV感知算法-PETR

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比5. PETRv2总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习下课程第四章——基…

Java EE 6 VS Spring 3:Java EE已经杀死了Spring? 没门!

介绍 几天前,我在听Java Spotlight Podcast的插曲85 。 在这次演讲中, Bert Ertman和Paul Bakker讨论了从Spring迁移到Java EE。 基本上,在他们的介绍中,他们说,如今,选择Spring而不是Java EE是没有意义的。…

usb检测串口是哪个角_怎样测试串口和串口线是否正常

一步:把串口线或者USB转串口线插到计算机上。二步:打开串口调试助手接着选择串口,串口线和 USB 转串口的端口号查看路径:电脑上--右键--属性--硬件--设备管理器-端口(COM 和LPT),点开端口前面的号查看即可。注释:1、US…

NodeJS常用模块介绍

收集了NodeJS开发中常用的一些模块。MVC框架 - Express Express 是轻量灵活的Nodejs Web应用框架,它可以快速地搭建网站。Express框架建立在Nodejs内置的Http模块上,并对Http模块再包装,从而实际Web请求处理的 功能。它支持多种前端模板&…

Java泛型面试问题

Java面试中的通用面试问题在相当长的时间内在Java 5周围越来越普遍,许多应用程序都转移到Java 5上,并且几乎所有新的Java开发都发生在Tiger(Java 5的代号)上。 泛型和Java 5功能(例如Enum)的重要性&#xf…

隐层元素闪一下_太阳一直依靠什么元素在燃烧,地球上的重元素又是怎么来的?...

本文基于回答网友一个这样的问题:太阳目前氢核聚变是氦碳氧稳定燃烧地球上的铁镍重元素哪里来的?可以说,这是一个毫无逻辑乱七八糟的问题,但既然邀请回答,就从中挑出几个稍显合理的问题说明一下。太阳核心每时每刻都在…

基于Token的WEB后台认证机制

基于Token的WEB后台认证机制 几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RESTful API 使用的最简单的认证方式,只需提供用户名密码即可&#xf…

JSF基于事件的沟通:过时的方法

用JSF编写的Web应用程序由相互交互的bean组成。 在开发Web应用程序时,bean之间的通信是主要的设计模式之一。 有时,一个bean需要向其他bean发送事件,以通知它们某些更改或其他任何更改。 我们通常可以将托管bean或Spring bean注入另一个bean的…

mysql调优 基础

MySQL调优可以从几个方面来做:1. 架构层:做从库,实现读写分离;2.系统层次:增加内存;给磁盘做raid0或者raid5以增加磁盘的读写速度;可以重新挂载磁盘,并加上noatime参数,这…

saltstack

第一:安装前准备: 声明我用的是ubuntu 16.04的系统 1.修改主机名,并保证两台机器可以互相ping同主机名 ip1 master_hostname ip2 slave_hostname 第二:安装 服务器安装 yum install salt-master -y客户端安装 yum install salt…

ios 百度地图指定区域_获取百度地图可视区域范围的数据

有个业务场景,需要根据获取到的地图区域显示,根据相应的经纬度反查 左侧区域的会议室。思路:1.得到百度地图可视区域--可视区域的中心点2.可视区域的四个角的其中两个(东北角西南角)http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_refer…

使用WS-Trust / STS采样器扩展JMeter

JMeter没有对WS-Security或WS-Trust的任何内置支持,这使我为JMeter开发了此STS Sampler –可以在负载测试STS时使任何人的生活变得更好。 首先,您需要拥有Apache JMeter发行版。 我正在使用v2.7。 然后,您可以从此处下载sts.sampler.zip –解…

分享一个使用闭包对一个对象继承方式

function Person(name,age){this.name name;this.age age; }//定义一个new函数 继承了对Person的继承 function New(obj){return function(){var o {"__proto__":obj.proto};obj.apply(o,arguments);}return obj; }var n new New(Person)("对象继承了person…

vue怎么改logo_vue全家桶项目构建教程

前言vue是现阶段很流行的前端框架,很多人通过vue官方文档的学习,对vue的使用都有了一定的了解,但再在项目工程化处理的时候,却发现不知道改怎么更好的管理自己的项目,如何去引入一些框架以及vue全家桶其他框架的使用&a…

EclipseLink MOXy作为JAXB提供者

EclipseLink MOXy是JAXB提供程序,并且是内置在JDK中的默认JAXB提供程序的引人注目的替代品。 首先是一个简单的测试,将Java对象编组为XML: 这是模型: XmlRootElement(nameMemberDetailsRequest, namespacehttp://bk.org/members…

monkeyrunner多点触摸

思路是:在屏幕上某个位置按着不放:device.touch(x,y,md.DOWN) 然后再做一个滑动的操作:device.drap((x1,y1),(x2,y2),0.2,10) 然后再松开按键:device.touch(x,y,md.UP) #codeing:utf-8 from com.android.monkeyrunner import Monk…

雅虎前端优化的35条军规

阅读目录 内容部分css部分js部分javascript, css 图片 cookie移动端 服务器摘要:无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化34条军规&…

stm32 内部sram大小_在SRAM、FLASH中调试代码的配置方法(附详细步骤)

聊天界面发送嵌入式大杂烩获取1TB大杂烩资料包STM32的FLASH擦写次数有限(大概为1万次),所以为了延长FLASH的使用时间,我们平时调试时可以选择在SRAM中进行硬件调试。除此之外,SRAM 存储器的写入速度比在内部 FLASH 中要快得多,所以…