设计模式--单例模式(Singleton)
单例模式(Singleton)
在有些系统中,为了节省内存资源、保证数据内容的⼀致性,对某些类要求只能创建⼀个实例,这就是所谓的单例模式。
单例模式的定义与特点
单例(Singleton)模式的定义:
指⼀个类只有⼀个实例,且该类能⾃⾏创建这个实例的⼀种模式。例如,Windows 中只能打开⼀个任务管理器,这样可以避免因打开多个任务管理器窗⼝⽽造成内存资源的浪费,或出现各个窗⼝显⽰内容的不⼀致等错误。
在计算机系统中,还有 Windows 的回收站、操作系统中的⽂件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应⽤程序的⽇志对象、数据库的连接池、⽹站的计数器、Web 应⽤的配置对象、应⽤程序中的对话框、系统中的缓存等常常被设计成单例。
单例(Singleton)模式的特点:
1.单例类只有⼀个实例对象;
2.该单例对象必须由单例类⾃⾏创建;
3.单例类对外提供⼀个访问该单例的全局访问点;
单例模式的结构与实现
单例模式是设计模式中最简单的模式之⼀。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来⽣成多个实例。但是,如果将类的构造函数设为私有的,外部类就⽆法调⽤该构造函数,也就⽆法⽣成多个实例。这时该类⾃⾝必须定义⼀个静态私有实例,并向外提供⼀个静态的公有函数⽤于创建或获取该静态私有实例。
下⾯来分析其基本结构和实现⽅法。
1. 单例模式的结构
单例模式的主要⾓⾊如下。
单例类: 包含⼀个实例且能⾃⾏创建这个实例的类。
访问类: 使⽤单例的类。
其结构如图 1 所⽰。
2. 单例模式的实现
Singleton 模式通常有两种实现形式。
第 1 种:懒汉式单例
该模式的特点是类加载时没有⽣成单例,只有当第⼀次调⽤ getlnstance ⽅法时才去创建这个单例。代码如下:
public class LazySingleton
{
private static volatile LazySingleton instance=null;//保证 instance 在所有线程中同步
private LazySingleton(){}//private 避免类在外部被实例化
public static synchronized LazySingleton getInstance()
{
//getInstance ⽅法前加同步
if(instance==null)
{
instance=new LazySingleton();
}
return instance;
}
}
注意:如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程⾮安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
第 2 种:饿汉式单例
该模式的特点是类⼀旦加载就创建⼀个单例,保证在调⽤ getInstance ⽅法之前单例已经存在了。
public class HungrySingleton
{
private static final HungrySingleton instance=new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance()
{
return instance;
}
}
饿汉式单例在类创建的同时就已经创建好⼀个静态的对象供系统使⽤,以后不再改变,所以是线程安全的,可以直接⽤于多线程⽽不会出现问题。
单例模式的应⽤实例
【例】⽤懒汉式单例模式模拟产⽣美国当今总统对象。
分析:在每⼀届任期内,美国的总统只有⼀⼈,所以本实例适合⽤单例模式实现,图 2 所⽰是⽤懒汉式单例实现的结构图。
程序代码如下:
public class SingletonLazy
{
public static void main(String[] args)
{
President Instance();
President Instance();
if(zt1==zt2)
{
System.out.println("他们是同⼀⼈!");
}
else
{
System.out.println("他们不是同⼀⼈!");
}
}
}
class President
{
private static volatile President instance=null;//保证instance在所有线程中同步//private避免类在外部被实例化
private President()
{
单例模式的几种实现方式System.out.println("产⽣⼀个总统!");
}
public static synchronized President getInstance()
{
//在getInstance⽅法上加同步
if(instance==null)
{
instance=new President();
}
else
{
System.out.println("已经有⼀个总统,不能产⽣新总统!");
}
return instance;
}
public void getName()
{
System.out.println("我是美国总统:特朗普。");
}
}
程序运⾏结果如下:
产⽣⼀个总统!
我是美国总统:特朗普。
已经有⼀个总统,不能产⽣新总统!
我是美国总统:特朗普。
他们是同⼀⼈!
【例】⽤饿汉式单例模式模拟产⽣猪⼋戒对象。
分析:同上例类似,猪⼋戒也只有⼀个,所以本实例同样适合⽤单例模式实现。本实例由于要显⽰猪⼋戒的图像,所以⽤到了框架窗体JFrame 组件,这⾥的猪⼋戒类是单例类,可以将其定义成⾯板 JPanel 的⼦类,⾥⾯包含了标签,⽤于保存猪⼋戒的图像,客户窗体可以获得猪⼋戒对象,并显⽰它。图 3 所⽰是⽤饿汉式单例实现的结构图。
程序代码如下:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论