在IOC容器中, 所有的對象默認都是單例, 我們只需要把對象加載到IOC容器中即可.
nutz demo:
@IocBean
public class SingletonDemo {
}
public class SingletonDemoTest {
private static Ioc ioc;
@BeforeClass
public static void setUp() throws Exception {
ioc = new NutIoc(new AnnotationIocLoader("me.lihongjie"));
}
@Test
public void ShouldGetSameInstance() throws Exception {
Assert.assertThat(ioc.get(SingletonDemo.class), Is.is(ioc.get(SingletonDemo.class)));
}
}
就這樣一個簡單的單例模式就實現了, 對於開發來說省卻了不少樣板代碼(雙檢查鎖), 對於學習來說, 我仍然希望能夠自己實現一個單例模式.
學習最重要的是一個推導以及整理的過程, 這樣才能夠完善自己的思維模式, 所以下面的代碼不是網絡上隨手複製的, 而是一步步完善出來的.
step 1 : 非單例模式
public class SingletonDemo {
public SingletonDemo() {
}
}
step 2: 封裝: 封裝我們不希望外界使用的關鍵字 : new
public class SingletonDemo {
// 封裝 new 之後無法直接實例化對象, 只能使用類方法
public static SingletonDemo newInstance(){
return new SingletonDemo();
}
public SingletonDemo() {
}
}
step 3 : 修改封裝的內部實現, 使其單例化:
public class SingletonDemo {
private static SingletonDemo instance = new SingletonDemo();
// 封裝 new 之後無法直接實例化對象, 只能使用類方法
public static SingletonDemo newInstance(){
return instance;
}
public SingletonDemo() {
}
}
step 4: 優化單例實現, 使其懶加載:
public class SingletonDemo {
private static SingletonDemo instance;
// 封裝 new 之後無法直接實例化對象, 只能使用類方法
public static SingletonDemo newInstance(){
// 只有在第一次調用時纔會加載
if (instance == null) {
return new SingletonDemo();
}
return instance;
}
public SingletonDemo() {
}
}
step 5: 優化懶加載單例實現, 使其線程安全:
public class SingletonDemo {
private static SingletonDemo instance;
// 封裝 new 之後無法直接實例化對象, 只能使用類方法
// 線程同步
public static synchronized SingletonDemo newInstance() {
if (instance == null) {
return new SingletonDemo();
}
return instance;
}
public SingletonDemo() {
}
}
step 6: 優化線程安全版懶加載, 縮小線程同步範圍
public class SingletonDemo {
private static SingletonDemo instance;
// 封裝 new 之後無法直接實例化對象, 只能使用類方法
// 線程同步
public static SingletonDemo newInstance() {
if (instance == null) {
// 只同步if 代碼塊, 優化性能
synchronized (SingletonDemo.class) {
if (instance == null) {
return new SingletonDemo();
}
}
}
return instance;
}
public SingletonDemo() {
}
}
具體的代碼含義就不細說了, 這方面有許多博客都可以參考, 關鍵是單例模式實現的推導過程:
- 如果你只需要簡單的單例模式或者只想學習單例模式, 那麼到step 3 就足夠了, 因爲後面的內容是優化, 不是必須, 不要過早優化.
- 模式的演化是伴隨着一些需求的, 比如說: 懶加載, 多線程, 而這些演化並不是模式的核心內容, 以多線程爲例, 如果你學會了簡單的Java多線程模式然後自己優化也可以把step 3 後面的實現完成.