Java Singleton 模式(单身模式,单态模式)是一种创建型设计模式。用来保证在运行的应用程序中,一个Class只是实例化一次,也就是只有一个相应的对象存在。
Java Singleton 模式(单身模式,单态模式)是一种创建型设计模式。用来保证在运行的应用程序中,一个Class只是实例化一次,也就是只有一个相应的对象存在。在 web 程序中我们会用一个核心的分配功能的Servlet程序,在这里我们就可以运用这种设计模式了。
一般Singleton模式通常有几种种形式:
第一种形式:
定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton {
private Singleton(){}
// 在自己内部定义自己一个实例,是不是很奇怪?
// 注意这是private 只供内部调用
private static Singleton instance = new Singleton();
// 这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
第二种形式:
public class Singleton{
private static Singleton instance=null;
public static Singleton getInstance(){
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if(instance==null)
instance=new Singleton();
return instance;
}
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
| Java Singleton模式属于管理实例化过程的设计模式家族。Singleton是一个无法实例化的对象。这种设计模式暗示,在任何时候,只能由JVM创建一个Singleton(对象)实例。 Singleton模式的运行机制 以下是Singleton模式的一个典型例子: public class Singleton { private final static Singleton INSTANCE = new Singleton(); // Private constructor suppresses generation of // a (public) default constructor private Singleton() {} public static Singleton getInstance() { return INSTANCE; } } 标准的Singleton模式并不使用直接静态变量实例化进行声明——它实例化构造器中的一个静态实例变量,而不查看它是否已经存在: public class ClassicSingleton { private static ClassicSingleton INSTANCE = null; private ClassicSingleton() { // Exists only to defeat instantiation. } public static ClassicSingleton getInstance() { if(INSTANCE == null) { INSTANCE = new ClassicSingleton(); } return INSTANCE; } } Singleton类的默认构造器被设为私有,这样做可防止其它类使用new关键字直接将对象实例化。对返回Singleton对象的实例方法应用一个静态修饰符,这使得它成为一个类级方法,不创建对象即可进行访问。 何时需要使用Singleton 当你只需要一个类实例时,Singleton才真正有用;如果类拥有几个实例,使用Singleton就不再适用。 设计系统时,你通常希望控制对象的用法,防止用户(包括你自己)复制对象或建立新实例。例如,你可以使用它创建一个连接池。每次程序需要往数据库中写入内容时才创建一个新连接的做法并不明智;相反,一个或一组已经在池中的连接就可以使用Singleton模式实例化。 Singleton模式常常和工厂方法模式一同使用,创建一个系统级资源,使用这个资源的代码并不知道它的特殊类型。抽象窗口工具包(AWT)就是组合使用这两个模式的典型例子。在GUI应用程序中,对每个应用程序实例,你一般只需要一个图形元素的实例,如打印(Print)对话框或OK按钮。 注意潜在的问题 虽然Singleton设计模式是最简单的设计模式之一,但它也存在一些缺陷。 多线程应用程序中的构造问题 在多线程应用程序中,你必须仔细构造Singleton模式。当Singleton不存在时,如果两个线程即将同时执行创建方法,这两个线程必须检查Singleton实例,但只有一个线程应当创建新对象。这个问题的典型解决办法就是对类使用相互排斥,指出对象正在被实例化。这是Singleton的一个线程安全的版本: public class Singleton { // Private constructor suppresses generation // of a (public) default constructor private Singleton() {} private static class SingletonHolder { private final static Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } 另一个解决办法是在getInstance()方法声明中添加synchronized关键字: public static synchronized Singleton getInstance() 提前考虑克隆预防 你仍然可以使用对象的clone()方法克隆对象,建立一个Singleton对象。要禁用这一功能,你需要禁用对象的克隆方法,这产生一个CloneNotSupportedException例外。 public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } 考虑使singleton类位于最后 你可能希望将Singleton类放在最后,以避免Singleton的子类造成其它问题。 不要忘记垃圾收集 根据不同的执行,你的Singleton类和它的所有数据可能被当作垃圾收集。因此,在应用程序运行时,你必须保证存在一个Singleton类的实时引用。 结论 Singleton模块得到广泛地使用,并证实可用于软件设计。虽然这个模式并非Java专有,但它已成为Java编程的一个典型应用。尽管这个模式相当简单,但还是要记住我在本文中描述的Singleton模式的限制。 |
即使是简单的脚本语言,应用良好的模式可以得到非常“优美”的代码和较高的效率。
尤其是对于交互要求较高的B/S系统,非常有必要用设计模式来优化代码。
单件模式(Singleton Pattern)是一种非常基本和重要的创建型模式。
“单件”的职责是保证一个类有且只有一个实例,并提供一个访问它的全局访问点。
在程序设计过程中,有很多情况下需要确保一个类只能有一个实例。
传统的编程语言中为了使一个类只有一个实例,最容易的方法是在类中嵌入静态变量,并在第一个实例中设置该变量,而且每次进入构造函数都要做检查,不管类有多少个实例,静态变量只能有一个实例。为了防止类被多次初始化,要把构造函数声明为私有的,这样只能在静态方法里创建一个实例。
在javascript中,虽然我们仍然可以指定静态方法来构造对象,但由于我们不能利用构造函数的“私有”来禁止多个实例的生成,因此要完全实现Singleton并没有想象中那么简单。
请看下面的例子:
[code]
<script>
function SingletonObject()
{
SingletonObject.prototype.methodA = function()
{
alert('methodA');
}
SingletonObject.prototype.methodB = function()
{
alert('methodB');
}
SingletonObject.instance = this;
}
SingletonFactory = new Object();
SingletonFactory.getInstance = function()
{
if(SingletonObject.instance == null)
return new SingletonObject();
else
return SingletonObject.instance;
}
var instA = SingletonFactory.getInstance();
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
var instC = new SingletonObject();
instC.methodA();
alert(instA == instC); //失败
</script>
[/code]
上面的例子试图通过传统的方式来实现Singleton模式,而通过调用SingletonTest.getInstance()来获得对象确实可以保证“唯一实例”,然而,这个例子的失败之处在于它并没有有效地禁止Singleton对象的构造,因此如果我们在程序代码中人工加入new SingletonObject(),仍然可以获得到多个对象而导致模式失败。
一个改进的替代方案如下:
[code]
<script>
function SingletonObject()
{
if(SingletonObject.instance != null)
{
alert("不能创建多个singleton实例!");
throw new Error();
}
SingletonObject.prototype.methodA = function()
{
alert('methodA');
}
SingletonObject.prototype.methodB = function()
{
alert('methodB');
}
SingletonObject.instance = this;
}
SingletonFactory = new Object();
SingletonFactory.getInstance = function()
{
if(SingletonObject.instance == null)
return new SingletonObject();
else
return SingletonObject.instance;
}
var instA = SingletonFactory.getInstance();
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
try
{var instC = new SingletonObject(); }//抛出异常
catch(e)
{alert('系统成功抛出了异常,阻止了instC的构造!');}
</script>
[/code]
这样当用户试图自己创建多个对象的时候,通过人工抛出异常来阻止。不过这么做还是有一点点违反了"初衷",即没有满足“必须通过静态方法来构造唯一实例”这个基本条件。因为用户可以在最开始的时候还是可以采用new操作符来构造对象,比如在一开始写var instA = new SingletonObject()来构造instA并不会导致抛出异常,这不能不说是这种方法的一个缺陷。
于是我们进一步思考,得到了下面第三种方法,这种方法巧妙利用了“匿名”函数的特征来禁止对SingletonObject类构造函数的访问,可以说比较好的模拟了私有构造函数的特性,从而比较完美地解决了用javascript实现Singleton Pattern的问题。
[code]
<script>
(function(){
//instance declared
//SingletonFactory Interface
SingletonFactory = {
getInstance : getInstance
}
//private classes
function SingletonObject()
{
SingletonObject.prototype.methodA = function()
{
alert('methodA');
}
SingletonObject.prototype.methodB = function()
{
alert('methodB');
}
SingletonObject.instance = this;
}
//SingletonFactory implementions
function getInstance()
{
if(SingletonObject.instance == null)
return new SingletonObject();
else
return SingletonObject.instance;
}
})();
var instA = null;
try
{
alert("试图通过new SingletonObject()构造实例!");
instA = new SingletonObject();
}
catch(e){alert("SingletonObject构造函数不能从外部访问,系统抛出了异常!");}
instA = SingletonFactory.getInstance(); //通过Factory上定义的静态方法获得
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
var instC = null;
try
{
alert("试图通过new SingletonObject()构造实例!");
instC = new SingletonObject();
}
catch(e){alert("SingletonObject构造函数不能从外部访问,系统抛出了异常!");}
</script>
[/code]
| 单件模式:用来创建这样一种类,这种类最多只能被实例化一次. 简单工厂模式又叫静态工厂模式,是用来实例化目标类的静态类。 |
Singleton Pattern
| Newpoo 发表于 2008-1-28 2:23:00 |
| Partly from : http://en.wikipedia.org/wiki/Singleton_pattern the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. Sometimes it is generalized to systems that operate more efficiently when only one or a few objects exist. ![]() Make sure both default constructor and copy constructor are private. |
public class Singleton { private final static Singleton instance = new Singleton(); // Private constructor suppresses generation of a (public) default constructor private Singleton() {} public static Singleton getInstance() { return instance; } }public class Singleton { private static Singleton instance; // Private constructor suppresses generation of a (public) default constructor private Singleton() {} public static synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } }public class Singleton { // Private constructor suppresses generation of a (public) default constructor private Singleton() {} private static class SingletonHolder { private static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }public class Singleton { private volatile static Singleton instance; // Private constructor suppresses generation of a (public) default constructor private Singleton() {} public static Singleton getInstance() { if(instance == null) { synchronized(Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; } }编者按:程序中经常有这样的要求,整个程序运行时只有一个实例被使用。比如:数据库连接池,系统参数配置,Java API 中的 Runtime, Calendar ...如何实现这种需求成为一个值得讨论的问题。让我们来看看本文的例子。
A.常见的例子
以往的做法,是在程序的某个类里面(比如是 GlobalObject )建立一个这个此种类的实例,然后规定所有需要用到此类的,都从 GlobalObject 那里获得,看下面的例子:
public class ConnectionPoolManager {
public ConnectionPoolManager {
// do some initialize work
}
public Connection getConnection(){
....
}
}
public class GlobalObject {
private ConnectionPoolManager connectionPoolManager;
public GlobalObject () {
connectionPoolManager = new ConnectionPoolManager();
...
}
public void getConnectionPoolManager() {
return connectionPoolManager;
}
}
public class QueryFunctions {
public static Collection findStudentByName(String name){
ConnectionPoolManager = globalObject.getConnectionPoolManager();
Connection connection = connectionPoolManager.getConnection();
// query database
}
}
但这样做有如下缺点:其他人可能 调用 ConnectionPoolManager 的构造函数自己建立一个 数据库连接池,导致程序中存在多个 ConnectionPoolManager,人为的规定往往得不到好的实施。
GlobalObject 其实就是一个 C 语言中的全局变量,与面向对象的方法相冲突。
新的方法实践过程
B.使用新的方法
因此,可以使用 设计模式 中的 Singleton (单件)模式来完成以上的需求:
Java API 中的 Runtime 等等用的就是这种方法。
代码如下:
public class ConnectionPoolManager {
private static instance = null;
private ConnectionPoolManager() {
// do some initialize work
}
public static void getInstance() {
if (instance == null){
instance = new ConnectionPoolManager();
}
return instance;
}
public Connection getConnection(){
}
}
ConnectionPoolManager 的使用
public class QueryFunctions {
public static Collection findStudentByName(String name){
ConnectPoolManager connectionPoolManager = ConnectionPoolManager.getInstance();
Connection conn = connectionPoolManager.getConnection();
// query database
}
}
1.instance 是私有的,开始时赋值为 null,外部只有通过 getInstance 方法才能获得他。
2.构造方法是私有的,这点很重要,保证只有这个类自己才能够调用,其他的类无法调用此构造函数。
3.getInstance 方法中:if 语句,保证只有一个 instance 存在唯一的一个 ConnectionPoolManager 在第一次调用的时候被建立。
C.另一个特殊实例
下面是另一个例子: java.lang.Runtime
我刚看了 Runtime 的实现如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don‘t let anyone else instantiate this class */
// 够狠
private Runtime() {}
}它在定义变量时创建 唯一的 Runtime 实例。
Java语言在设计的时候就使用了很多 设计模式的思想,像 Collection 中的 Iterator 模式,
Event 中的 Observer 模式,Applet 中的 Templete 模式,对象创建时的 Factory 模式,这些
模式大多可以从 Java 的类的命名中体现出来,希望大家在学习 Java 时多注意对 设计模式 的学习。参考:
设计模式:可复用面向对象软件的基础 (Gang of Four 的 Design Pattern 经典)
Thinking in Pattern : http://www.mindview.net/Books/TIPatterns/ 还是 Bruce Eckel 写的。
Design Pattern Java : ftp://cinc.dns2go.com/pub/doc/pattern/java
在java中singleton是什么模式?悬赏分:0 - 解决时间:2007-11-17 23:27
在java中singleton是什么模式?我书上写的不是很详细!只是说singleton模式被用来限制对象的创建,不能有子类,构造函数是私有的,而且一般提供一个静态方法getInstance()来得到一个实例! 提问者: paopao0611 - 经理 四级最佳答案单子模式又叫单例模式。 应用该模式时,实例化对象的类必须只有一个实例存在。主要应用在整个系统只需要一个全局对象,有利于协调系统的整体行为。单例模式,不管你事例化多少个这个类的对象,
其实都只存在一个对象。
构造函数私有,就是屏蔽了构造方法,不能由构造方法来产生对象。
因此你可以自己写个getInstance()..由此,就可以控制整个系统中,只存在一个此类的对象。
你可以上网搜一搜有关单子模式的内容单例模式的好处就是:类只实例化一次,省资源,节省开销,提高速度
下边写的是什么还没怎么看懂,再提高提高再回过头来看吧,先存在这
Java Singleton 模式用来保证在运行的应用程序中,一个Class只是实例化一次,也就是只有一个相应的对象存在。在 web 程序中我们会用一个核心的分配功能的Servlet程序,在这里我们就可以运用这种设计模式了。
一般Singleton模式通常有几种种形式:
第一种形式:
定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton { private Singleton(){} //在自己内部定义自己一个实例,是不是很希奇? //注重这是private 只供内部调用 private static Singleton instance = new Singleton(); //这里提供了一个供外部访问本class的静态方法,可以直接访问 public static Singleton getInstance() { return instance; } } 第二种形式:
public class Singleton { private static Singleton instance = null; public static synchronized Singleton getInstance() { //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 //使用时生成实例,提高了效率! if (instance==null) instance=new Singleton(); return instance; } }
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
转发至微博
转发至微博
评论