1. 單例設(shè)計模式(Singleton)
在正常情況下,如果有一個類,那么只有通過產(chǎn)生對象之后才可以操作這個類
范例:觀察如下代碼
class Singleton {
public void print() {
System.out.println("Hello world!");
}
}
public class SingletonDemo {
public static void main(String[] args) {
Singleton s = null; //聲明對象
s = new Singleton(); //實例化對象
s.print();
}
}
現(xiàn)在Singleton類里面存在有構(gòu)造方法,如果沒有明確定義一個構(gòu)造的話,會自動在編譯的時候生成一個無參的,什么都不做的構(gòu)造方法,即:一個類至少會保留一個構(gòu)造方法。
范例:修改Singleton類的構(gòu)造方法
class Singleton {
private Singleton(){} //構(gòu)造方法私有化
public void print() {
System.out.println("Hello world!");
}
}
一旦構(gòu)造方法私有化,外部將無法直接通過關(guān)鍵字new來進行對象的實例化操作。
范例:錯誤的代碼
public static void main(String[] args) {
Singleton s = null; //聲明對象
//錯誤代碼
s = new Singleton(); //實例化對象
s.print();
}
如果修改代碼才能夠得到Singleton類的實例化對象,并且調(diào)用到print()方法?
分析步驟:
- 構(gòu)造方法上使用了private聲明
private Singleton(){},那么就表示這個構(gòu)造方法只能夠被類的內(nèi)部所使用;既然如此,可以直接在類的內(nèi)部實例化一個對象:
class Singleton {
//直接在類內(nèi)部實例化對象
Singleton instance = new Singleton();
private Singleton(){} //構(gòu)造方法私有化
public void print() {
System.out.println("Hello world!");
}
}
- 現(xiàn)在的instance在Singleton里面只是一個普通的類屬性,而所有的普通類屬性必須在類產(chǎn)生實例化之后才可以使用,是否存在一種方式,可是讓這個類屬性不受Singleton類實例化對象的控制呢?
如果使用static聲明instance屬性,就可以表示在一個類沒有產(chǎn)生實例化對象的時候直接使用屬性。
class Singleton {
//直接在類內(nèi)部實例化對象,用static聲明
static Singleton instance = new Singleton();
private Singleton(){} //構(gòu)造方法私有化
public void print() {
System.out.println("Hello world!");
}
}
public class SingletonDemo {
public static void main(String[] args) {
Singleton s = null; //聲明對象
s = Singleton.instance; //直接訪問static屬性
s.print();
}
}
- 在一個類定義的時候應(yīng)該對屬性進行封裝
private static Singleton instance = new Singleton();
- 一旦封裝之后如果想要訪問此屬性只能通過getter()方法,那么就需要提供一個getter()方法,而且同樣要不受到Singleton實例化對象的控制,所以繼續(xù)使用static屬性
class Singleton {
//直接在類內(nèi)部實例化對象,用static聲明
private static Singleton instance = new Singleton();
private Singleton(){} //構(gòu)造方法私有化
public static Singleton getInstance() {
return instance;
}
public void print() {
System.out.println("Hello world!");
}
}
代碼意義:
如果要想控制一個類中實例化對象的產(chǎn)生個數(shù),那么首先要鎖定類中的構(gòu)造方法,因為在實例化任何新對象都要使用構(gòu)造方法,如果構(gòu)造方法被鎖了,那么就無法產(chǎn)生新的實例化對象了。
既然需要是一個實例化對象,那么就可以在類的內(nèi)部使用static方法來定義一個公共的對象,并且通過static方法返回唯一的對象,這樣外部不管有多少次調(diào)用,對只會產(chǎn)生唯一的對象,這樣的設(shè)計就屬于單例設(shè)計模式(Singleton)。
面試題:編寫Singleton程序,并解釋Singleton程序的特點。
class Singleton {
//直接在類內(nèi)部實例化對象,用static聲明
private static final Singleton INSTANCE = new Singleton();
private Singleton(){} //構(gòu)造方法私有化
public static Singleton getInstance() {
return INSTANCE;
}
public void print() {
System.out.println("Hello world!");
}
}
public class SingletonDemo {
public static void main(String[] args) {
Singleton s = null; //聲明對象
s = Singleton.getInstance(); //直接訪問static屬性
s.print();
}
}
程序特點:構(gòu)造方法私有化,在類的內(nèi)部定義static屬性方法,利用static方法取得本類的實例化對象,這樣不管外部會產(chǎn)生多少個Singleton類的對象,但實際上只產(chǎn)生唯一的對象。
單例設(shè)計模式有兩種形式:餓漢式、懶漢式餓漢式:上面編寫的代碼就是餓漢式的應(yīng)用,在Singleton類定義的時候就已經(jīng)準備好了一個Singleton類的實例化對象INSTANCE,而并沒有關(guān)心這個對象是否使用。
懶漢式:最大的特點就在于它是在第一次使用的時候才進行實例化操作
范例:實現(xiàn)懶漢式
class SingletonLazy{
private static Singleton instance;
private static SingeletonLazy(){}
public static SingletonLazy getInstance() {
if (instance == null) { //此時還沒有實例化
instance = new SingeletonLazy(); //實例化對象
}
return instance;
}
public void print(){
System.out.println("Hello world!");
}
}
2. 多例設(shè)計模式
多例設(shè)計模式,可以讓一個類產(chǎn)生指定多個個數(shù)的實例化對象。
例如:
- 定義一個表示一周天數(shù)的類,這個類智能取七個對象;
- 定義一個表示性別的類,這個類智能取兩個對象
范例:定義一個表示性別的類
class Sex {
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex WOMALE = new Sex("女");
private Sex(String title) { //構(gòu)造方法私有化
this.title = title;
}
public String toString() {
return this.title;
}
public static Sex getInstance(int ch){
switch (ch) {
case 1:
return MALE;
case 2:
return WOMALE;
default:
return null;
}
}
}
public class MultionDemo {
public static void main(String[] args) {
Sex sex = Sex.getInstance(2);
System.out.println(sex);
}
}
3. 總結(jié)
- 單例設(shè)計模式就是一個類只能產(chǎn)生唯一的實例化對象;
- 多例設(shè)計模式可以產(chǎn)生多個對象,要取得的時候需要加上標記,
單例和多例設(shè)計的核心:構(gòu)造方法私有化