天天看點

設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點

                                          享元模式

1概述

設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點

2 結構 

設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點
設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點
public class MyCharacter {
	private char mychar;
	
	public MyCharacter(char mychar) {
		this.mychar = mychar;
	}
	
	public void display() {
		System.out.println(mychar);
	}
}           
public class MyCharacterFactory {
	private Map<Character,MyCharacter> pool;
	
	public MyCharacterFactory() {
		pool = new HashMap<Character,MyCharacter>();
	}
	
	public MyCharacter getMyCharacter(Character character) {
		MyCharacter myChar = pool.get(character);
		if(myChar == null) {
			myChar = new MyCharacter(character);
			pool.put(character, myChar);
		}
		return myChar;
	}
}
           
設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點
設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點
設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點

代碼示例說明

public class Person {
	private String name;
	private int age;
	private String sex;
	
	public Person(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	
	public Person() {
		
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	
	
}
           
public class Teacher extends Person {
	private String number;
	
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public Teacher(String name, int age, String sex,String number) {
		super(name, age, sex);
		this.number = number;
	}
	
	public Teacher() {
		super();
	}
	
}
           
public class TeacherFactory {
	private Map<String,Teacher> pool;
	
	public TeacherFactory() {
		pool = new HashMap<String,Teacher>();
	}
	
	public Teacher getTeacher(String number) {
		Teacher teacher = pool.get(number);
		if(teacher == null) {
			teacher = new Teacher();
			teacher.setNumber(number);
			pool.put(number, teacher);
		}
		return teacher;
	}
}           
public class MainClass {
	public static void main(String[] args) {
		TeacherFactory factory = new TeacherFactory();
		Teacher teacher1 = factory.getTeacher("0102034");
		Teacher teacher2 = factory.getTeacher("0102035");
		Teacher teacher3 = factory.getTeacher("0102034");
		Teacher teacher4 = factory.getTeacher("0102037");
		
		System.out.println(teacher1.getNumber());
		System.out.println(teacher2.getNumber());
		System.out.println(teacher3.getNumber());
		System.out.println(teacher4.getNumber());
		
		if(teacher1 == teacher3) {
			System.out.println("true");
		} else {
			System.out.println("false");
		}
	}
}           

JDK源碼中用到的享元模式

String常量池和Integer等包裝類的緩存政策:Integer.valueOf(int i)

 1. 首先String不屬于8種基本資料類型

String是一個對象。因為對象的預設值是null,是以String的預設值也是null;但它又是一種特殊的對象,有其它對象沒有的一些特性。

2. new String()和new String(“”)都是申明一個新的空字元串,是空串不是null;

3. String str=”kvill”;

String str=new String (“kvill”);的差別:

在這裡,我們不談堆,也不談棧,隻先簡單引入常量池這個簡單的概念。

常量池(constant pool)指的是在編譯期被确定,并被儲存在已編譯的.class檔案中的一些資料。它包括了關于類、方法、接口等中的常量,也包括字元串常量。

String s0=”kvill”; 
String s1=”kvill”; 
String s2=”kv” + “ill”; 

System.out.println( s0==s1 ); 
System.out.println( s0==s2 );           
true 
true           

首先,我們要知結果為道Java會確定一個字元串常量隻有一個拷貝。

因為例子中的s0和s1中的”kvill”都是字元串常量,它們在編譯期就被确定了,是以s0==s1為true;而”kv”和”ill”也都是字元串常量,當一個字元串由多個字元串常量連接配接而成時,它自己肯定也是字元串常量,是以s2也同樣在編譯期就被解析為一個字元串常量,是以s2也是常量池中”kvill”的一個引用。

是以我們得出s0==s1==s2;

用new String() 建立的字元串不是常量,不能在編譯期就确定,是以new String() 建立的字元串不放入常量池中,它們有自己的位址空間。

String s0=”kvill”; 
String s1=new String(”kvill”); 
String s2=”kv” + new String(“ill”); 

System.out.println( s0==s1 ); 
System.out.println( s0==s2 ); 
System.out.println( s1==s2 );           

結果為:

false 
false 
false           

4. String.intern():

再補充介紹一點:存在于.class檔案中的常量池,在運作期被JVM裝載,并且可以擴充。String的intern()方法就是擴充常量池的一個方法;當一個String執行個體str調用intern()方法時,Java查找常量池中是否有相同Unicode的字元串常量,如果有,則傳回其的引用,如果沒有,則在常量池中增加一個Unicode等于str的字元串并傳回它的引用

String s0= “kvill”; 
String s1=new String(”kvill”); 
String s2=new String(“kvill”); 

System.out.println( s0==s1 ); 
System.out.println( “**********” ); 
s1.intern(); 
s2=s2.intern(); //把常量池中“kvill”的引用賦給s2 

System.out.println( s0==s1); 
System.out.println( s0==s1.intern() ); 
System.out.println( s0==s2 );           

結果為 

false 
********** 
false //雖然執行了s1.intern(),但它的傳回值沒有賦給s1 
true //說明s1.intern()傳回的是常量池中”kvill”的引用 
true           

5. 關于equals()和==:

這個對于String簡單來說就是比較兩字元串的Unicode序列是否相當,如果相等傳回true;而==是比較兩字元串的位址是否相同,也就是是否是同一個字元串的引用。

6. 關于String是不可變的

這一說又要說很多,大家隻要知道String的執行個體一旦生成就不會再改變了,比如說:String str=”kv”+"ill"+" "+"ans”;

就是有4個字元串常量,首先”kv”和”ill”生成了”kvill”存在記憶體中,然後”kvill”又和” “ 生成 ”kvill “存在記憶體中,最後又和生成了”kvill ans”;并把這個字元串的位址賦給了str,就是因為String的“不可變”産生了很多臨時變量,這也就是為什麼建議用StringBuffer的原因了,因為StringBuffer是可改變的。

7String 享元模式

享元模式在編輯器系統中大量使用,一個文本編輯器往往會提供很多種字型,而通常的做法就是将每一個字母做成一個享元對象。享元對象的内蘊狀态就是 這個字母,而字母在文本中的位置和字型風等其他資訊則是外蘊狀态,比如字母a可能出現在文本的很多地方,雖然這些字母a的位置和字型風格不同,但是所有這 些地方使用的都是同個字母對象,這樣一來,字母對象就可以在整個系統中共享

在Java語言中,String類型就使用了享元模式.String對象是不變對象,一旦建立出來就不能改變,如果需要改變一個字元串的值,就隻 好建立一個新的String對象,在JVM内部, String對象都是共享的。如果一個系統中有兩個String對象所包含的字元串相同的話,JVM實際上隻建立一個String對象提供給兩個引用,從 而實作String對象的共享,String的inern()方法給出這個字元串在共享池中的唯一執行個體.

享元模式應當在什麼情況下使用

(1)一個系統有大量的對象

(2)這些對象耗費大量的記憶體

(3)這些對象可以按照内蘊狀态分成很多的組,當把外蘊對象從對象中删除時,每一個組都可以僅用一個對象代替

(4)使用享元模式需要維護一個記錄了系統已有的所有享元的表,而這需要耗費資源,是以應當在有足夠多的享元實作可供共享時才值的使用享元模式.

享元模式的優點和缺點

享元模式的優點在于它大幅度地降低記憶體中的對象的數量,但是也為這一點付出了代價:

(1)為了使對象可以共享,需要将一些狀态外部化,這使得程式的邏輯複雜化

(2)享元模式将享元對象的狀态外部化,而讀取外部狀态使得運作時間稍微變長.

設計模式---享元模式                                          享元模式1概述2 結構 代碼示例說明JDK源碼中用到的享元模式享元模式應當在什麼情況下使用享元模式的優點和缺點

繼續閱讀