Singleton / 不可變類 / 緩存不可變類 的實(shí)現(xiàn)
Singleton(單例類)
單例類用的地方很多柏靶,如果一個(gè)類始終只能創(chuàng)建一個(gè)實(shí)例,則這個(gè)類被稱為單例類珠移。
以下程序是創(chuàng)建一個(gè)單例類:
public class SingletonTest {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
s1.setName("Singleton1");
System.out.println("s1 = " + s1.getName());
System.out.println("s2 = " + s2.getName());
s2.setName("Singleton2");
System.out.println("s1 = " + s1.getName());
System.out.println("s2 = " + s2.getName());
}
}
class Singleton {
private String name;
private static Singleton singleton = new Singleton("default");
private Singleton(String name) {
this.name = name;
}
public static Singleton getInstance() {
return singleton;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
不可變類
不可變類就是在創(chuàng)建該類的實(shí)例后不能更改該類的屬性。Java提供的8個(gè)包裝類和java.lang.String都是不可變類。
創(chuàng)建不可變類的幾個(gè)規(guī)則:
- 使用private 和 final 修飾符修飾屬性郊酒;
- 提供帶參數(shù)的構(gòu)建起,用于初始化屬性值键袱;
- 只提供getter方法燎窘;
- 重寫hashCode 和 equlas方法;
/**
* Person 類是一個(gè)不可變類
* @author wangmin
*
*/
public class Person {
private final String name;
private final int age;
public Person() {
this.name = "";
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public boolean equlas (Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
Person p = (Person)obj;
if (this.getName().equals(p.getName()) && this.age == p.getAge()) {
return true;
}
}
return false;
}
public int hasCode() {
return name.hashCode() + age;
}
}
緩存不可變類
如果程序經(jīng)常需要使用相同的不可變類實(shí)例蹄咖,則應(yīng)該考慮緩存這種不可變類褐健。下面是簡(jiǎn)單的使用數(shù)組的方式實(shí)現(xiàn)一個(gè)不可變類。
/**
* 使用數(shù)組的方式來(lái)緩解Person
* 1. 定義數(shù)組大小澜汤,并且使用private static 修飾
* 2. 定義valueOf方法獲取對(duì)象蚜迅,但是其中存在以下幾種情況:
* 2.1 循環(huán)遍歷整個(gè)緩存數(shù)組的大小,然后比較俊抵,如果已經(jīng)被緩存則直接取出谁不。(注意數(shù)組元素可能為null)
* 2.2 由2.1的結(jié)果可知,如果數(shù)組中沒(méi)有則新創(chuàng)建徽诲。
* 2.3 首次判斷pos是否已滿拍谐,如果已滿則將新的對(duì)象創(chuàng)建到數(shù)組0的位置烛缔,并且將pos設(shè)置為0,并返回轩拨。
* 2.4 如果沒(méi)有滿則根據(jù)pos的位置創(chuàng)建践瓷,并返回。
* @author wangmin
*
*/
public class CachePerson {
private static int MAX_SIZE = 10;
private static CachePerson[] cp = new CachePerson[MAX_SIZE];
private String name;
private static int pos = 0;
public CachePerson() {
}
public CachePerson(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public static CachePerson valueOf(String name) {
for (int i = 0; i < MAX_SIZE; i++) {
if (cp[i] != null && cp[i].getName().equals(name)) {
return cp[i];
}
}
if (pos == MAX_SIZE) {
cp[0] = new CachePerson(name);
pos = 1;
} else {
cp[pos++] = new CachePerson(name);
}
return cp[pos-1];
}
public boolean equlas (Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
CachePerson cp = (CachePerson)obj;
if (cp.getName().equals(this.getName())) {
return true;
}
}
return false;
}
public int hasCode() {
return name.hashCode();
}
}