您的位置:首页 > 编程语言 > Java开发

单列模式(Singleton Pattern、单态模式、单件模式、对象创建型模式)

2017-04-09 10:22 309 查看

意图

唯一的对象实例

保证一个类仅有一个实例,并提供一个访问他的全局访问点

有状态(可变的单例对象,可以组成状态仓库)、无状态(工具类)

适用性

在下面的情况下可以使用Singleton模式:

1. 当类只能有一个实例而且客户可以从一个总所周知的访问点访问它时。

2. 当这个唯一实例应该是通过子类可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

3. 系统只需要一个实例的对象,而这个对象又会被经常创建。

结构



参与者

Singleton

定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作。

可能负责创建它自己的唯一实例。

代码

懒汉

public class Singleton1 {
private Singleton1(){
}
private static Singleton1 instance=null;
public static synchronized Singleton1 getInstance(){
if(instance==null){
instance = new Singleton1();
}
return instance;
}
}


饿汉

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


单利注册工厂

public final class SingletonRegistryFactory implements FactoryInterface{
private static final int maxCapacity = 50;
private static final SingletonRegistryFactory singleRegistry = new SingletonRegistryFactory();
//保证线程安全
private Map<String,Object> singletonCache = Collections.synchronizedMap(new LRULinkedHashMap<String, Object>(maxCapacity));
/**
* 私有构造方法
*/
private SingletonRegistryFactory() {
}
public static SingletonRegistryFactory getInstance() {
return singleRegistry;
}

public Object getSingleton(String beanName) {
return this.singletonCache.get(beanName);
}

public void addSingleton(String beanName, Object sharedBean) {
synchronized (this.singletonCache) {
this.singletonCache.put(beanName, sharedBean);
}
}

public void removeSingleton(String beanName) {
synchronized (this.singletonCache) {
this.singletonCache.remove(beanName);
}
}

public void destroySingletons() {
synchronized (this.singletonCache) {
this.singletonCache.clear();
}
}
}


协作

客户职能通过Singleton的Instance操作访问一个Singleton的实例。

效果

对唯一实例的受控访问

因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。

缩小名空间

Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。

允许对操作和表示的精化

Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。

允许可变数目的实例

这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只允许访问Singleton实例的操作需要改变。

比类操作更灵活

另一种封装单件功能的方式是使用类操作。但这种语言技术难以改变设计你允许一个类有多个实例。此外,静态成员函数不是虚函数,因此子类不能多态的重定义它们。

优点

实例控制,保证实例的唯一性

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

缺点

需要提供详细文档提供开发者使用,防止开发混乱

不能解决删除单个对象的问题,可以使用缓存管理技术管理单例对象

实现

保证一个唯一的实例

Singleton模式使得这个唯一实例是类的一般实例,但该类被写成只有一个实例能被创建。做到这一点的一个常用方法是将创建这个实例的操作隐藏在一个类操作后面,由它保证只有一个实例被创建。这个操作可以访问保存唯一实例的变量,而且它可以保证这个变量在返回值之前用这个唯一实例初始化。这种方法保证了单件在它的首次使用前被创建和使用。

创建Singleton类的子类

主要问题与其说是定义子类不如说是建立它的唯一实例,这样客户就可以使用它。事实上,指向单件实例的变量必须用子类的实例进行初始化。最简单的技术是在Singleton的Instance操作中决定你想使用的是哪一个单件。

另一个选择Singleton的子类的方法是将Instance的实现从父类中分离出来,将它放入子类。

一个更灵活的方法是使用一个单件注册表(registry of singleton)。可能的Singleton类的集合不是由Instance定义的,Singleton类可以根据名字在一个众所周知的注册表中注册它们的单件实例。

这个注册表在字符串名字和单件之间建立映射。当Instance需要一个单件时,它参考注册表,根据名字请求单件。

经典例子

各种工具类的使用,建议使用缓存技术管理单例对象

Spring框架中实现的例子

package org.springframework.aop.framework.adapter;
/**
* Singleton to publish a shared DefaultAdvisorAdapterRegistry instance.
* 抽象化类使其不可实例化
* @author Rod Johnson
* @author Juergen Hoeller
* @author Phillip Webb
* @see DefaultAdvisorAdapterRegistry
*/
public abstract class GlobalAdvisorAdapterRegistry {
/**
* Keep track of a single instance so we can return it to classes that request it.
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
/**
* Return the singleton {@link DefaultAdvisorAdapterRegistry} instance.
*/
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
/**
* Reset the singleton {@link DefaultAdvisorAdapterRegistry}, removing any
* {@link AdvisorAdapterRegistry#registerAdvisorAdapter(AdvisorAdapter) registered}
* adapters.
*/
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}


相关模式

Abstract Factory Pattern中的具体工厂

Builder Pattern中的指导者

Facade Pattern中的Facade参与者

Prototype Pattern中的原型管理器

敬请期待“创建模式(Builder Pattern、构建模式、生成器,对象创建型模式)”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息