singleton即单例模式。【第1条】中我提到的Session性质的全局唯一实例既是单例模式。它只能被实例化一次,通常代表本质上具有唯一性质的东西。
除了Session的例子外,我这里还有一个很微妙的例子:
new MessageBox("Hello World ! ").show();
MessageBox.show(new MessageBox("Hello World ! ");
MessageBox.show("Hello World ! ");
MessageBox.getInstance().show("Hello World ! ");
很显然第一个是多实例模式,每次new的时候都会构造一个新的MessageBox类(如果MessageBox是非可变类,可能并非每次都会构造新的,如果碰巧形参的字符串曾经出现过,就不必再构造新的实例了)。
第二个使用一个静态方法(只是普通的静态方法)来显示消息框,但是作为传入的参数,还是一个刚刚被创建的MessageBox类。
第三个和第二个比较类似,只是少了一层“脱了裤子放屁”的new,直接把String作为参数给show()。现在是单例模式了吗?答案是可能是。也可能不是,而“进一步”是不可实例化的工具类(util),参考【第3条】。
第四个呢,从getInstance一眼就能看出,这不是【第1条】中刚刚讲到的静态工厂方法吗。OK,只要MessageBox的作者不是个糊涂的程序员,那么可以几乎可定它是一个单例模式。
那么如何才能保证一个类只能被实例化一次呢?(也就是说怎么才能说刚才那个MessageBox的作者不是个糊涂的程序员呢?)实现的方法有2种:这2种的共性是
1)都把构造函数声明为私有的,别人无法通过调用构造函数来创建类的事例了。
2)都有一个静态的成员,用来保持(保存)这个“单实例”
不同点是:
方法1)将这个静态成员声明为公有的,供他人直接使用。
public class Example{
public static final Example INSTANCE=new Example();
private Example(){ //构造函数为私有
...}
....
}
方法2)将这个静态成员声明为私有的,通过静态工厂方法供他人使用。
public class Example{
private static final Example INSTANCE=new Example();//改为私有
private Example(){ //构造函数为私有
...}
public static Example getInstance(){
return INSTANCE;
}
....
}
2种方法的优缺点其实并不大,由于第2种更为灵活,对将来的扩展也留有更多的余地,所以我个人还是更倾向于第2种。
我在开发的Framework中,单实例的应用并不多(一个项目中如果太多反而是要思考了),其中一个最突出的应用就是UserSession,它记录了客户的登录信息,显然一个用户只能有一个UserSession。
通常这样的类最好也是非可变的,见【第13条】。但是由于其他原因这里的UserSession无法做成非可变类,这个到【第13条】时再细说。
【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208
分享到:
相关推荐
私有构造器的使用方法可以分为两种,一种是使用私有构造器强化 Singleton 属性,另一种是使用私有构造器强化不可实例化的能力。对于第一种方法,可以使用私有构造器来实例化公有的静态 final 域,然后使用静态方法 ...
传统的C++单例实现可能使用静态成员变量和私有构造函数来达到这一目的: ```cpp class Singleton { private: Singleton() {} // 私有构造函数 static Singleton* instance; // 静态成员变量 public: static ...
在这段代码中,`Singleton`类的构造函数被声明为私有,这意味着不能直接通过`new`操作符创建`Singleton`对象。`Instance()`函数负责返回单例对象的引用。静态局部变量`singleton`确保在第一次调用`Instance()`时创建...
Singleton() {} // 构造函数私有化 Singleton(const Singleton&) {} // 复制构造函数禁用 Singleton& operator=(const Singleton&) {} // 赋值运算符禁用 static Singleton* instance; // 单例对象静态指针 ...
通常,我们会将构造函数设为私有(private),然后提供一个静态方法来获取类的唯一实例。这个静态方法通常被称为“单例方法”。 在Java中,实现单例模式有多种方式: 1. 饿汉式(Eager Initialization): 这种...
Singleton模式通常包含三个关键部分:私有化构造函数以防止外部直接实例化,一个静态成员变量用于存储唯一的实例,以及一个公共的静态方法(通常命名为getInstance)供外界获取这个唯一实例。 在C++中,Singleton的...
1. 私有化构造函数:Singleton类的构造函数通常声明为私有的,防止其他类通过new操作符直接创建实例。 2. 单例实例的静态成员变量:这个静态成员变量保存Singleton类的唯一实例。 3. 获取实例的方法:一个公共的静态...
1. 第一种形式的Singleton模式,通过私有构造函数防止直接实例化,同时在类内部创建一个私有的静态实例。通过一个公共的静态方法`getInstance()`返回这个唯一的实例。这种方法简单明了,但在多线程环境中可能存在...
Singleton() {} // 私有构造函数防止外部实例化 Singleton(const Singleton&) = delete; // 禁止拷贝构造 Singleton& operator=(const Singleton&) = delete; // 禁止赋值操作 }; ``` 这种方法简洁且线程安全...
在Java或Android中,通常通过私有构造函数和静态工厂方法来实现这一目标。这样可以防止其他类通过常规方式创建实例,确保单例的唯一性。 在Android中,Singleton模式的应用场景包括但不限于: 1. 应用程序配置管理...
2. **私有构造函数**:`private SingleTon() {}` 构造函数被声明为私有的,这意味着不能通过 `new SingleTon()` 的方式从类的外部创建新的实例。 3. **公共静态方法**:`public static SingleTon getInstance() {.....
Singleton() {} // 私有构造函数 Singleton(const Singleton&) {} // 私有拷贝构造函数 Singleton& operator=(const Singleton&) { return *this; } // 私有赋值运算符 static Singleton* instance; // 静态...
private Singleton() {} // 私有构造函数 public static synchronized Singleton getInstance() { // 同步方法 if (sing == null) { // 检查实例是否已经创建 sing = new Singleton(); // 创建新实例 } ...
// 私有构造函数,防止外部实例化 private Singleton() {} // 静态成员变量,保存唯一实例 private static final Singleton instance = new Singleton(); // 公共静态方法,返回唯一实例 public static ...
// 确保你的构造函数是私有的,防止外部直接实例化 MyClass() {} // 添加你需要的方法和成员变量 }; // 使用Loki的Singleton模板为MyClass创建一个单例 typedef Loki::SingletonHolder<MyClass> ...
这通常通过私有化构造函数和提供一个公共静态方法(称为单例工厂方法)来实现。在Java中,单例模式的实现有多种方式: 1. 饿汉式(Static Singleton):在类加载时就创建了唯一实例,线程安全,但可能会造成资源...
// 私有构造函数,防止外部实例化 private Singleton() {} // 使用静态内部类来初始化实例 private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } // ...
private Singleton() {} // 私有构造函数防止外部直接创建对象 public static Singleton getInstance() { return instance; } } ``` 这种方式在类加载时即完成了实例化,避免了线程同步问题,但可能会造成...
一种常见的C++单例模式实现方式是使用静态成员变量和私有构造函数: ```cpp #include class Singleton { private: Singleton() {} // 私有构造函数 static Singleton* instance; // 静态成员变量 public: ...
在这个例子中,`FinalClass2`可以正常实例化,无论是栈上还是堆上,但任何试图继承`FinalClass2`的尝试都会导致编译错误,因为它们在实例化时会尝试调用`MakeFinal`的私有构造函数,这是不允许的。 总结来说,虽然...