1. 程式人生 > >java幾種常用設計模式簡單示例

java幾種常用設計模式簡單示例

1.單例設計模式

       所謂單例設計模式簡單說就是無論程式如何執行,採用單例設計模式的類(Singleton類)永遠只會有一個例項化物件產生。具體實現步驟如下:

      (1) 將採用單例設計模式的類的構造方法私有化(採用private修飾)。

      (2) 在其內部產生該類的例項化物件,並將其封裝成private static型別。

      (3) 定義一個靜態方法返回該類的例項。

         示例程式碼如下:

Java程式碼 複製程式碼 收藏程式碼
  1. class Singleton {   
  2. privatestatic Singleton instance = new Singleton();
    // 在內部產生本類的例項化物件
  3. publicstatic Singleton getInstance() { // 通過靜態方法返回instance物件
  4. return instance;   
  5.     }   
  6. private Singleton() { // 將構造方法封裝為私有化
  7.     }   
  8. publicvoid print() {   
  9.         System.out.println("Hello World!!!");   
  10.     }   
  11. }   
  12. publicclass SingletonDemo {   
  13. publicstaticvoid main(String args[]) {   
  14.         Singleton s1 = 
    null// 宣告物件
  15.         Singleton s2 = null// 宣告物件
  16.         Singleton s3 = null// 宣告物件
  17.         s1 = Singleton.getInstance(); // 取得例項化物件
  18.         s2 = Singleton.getInstance(); // 取得例項化物件
  19.         s3 = Singleton.getInstance(); // 取得例項化物件
  20.         s1.print(); // 呼叫方法
  21.         s2.print(); // 呼叫方法
  22.         s3.print(); // 呼叫方法
  23.     }   
  24. }  
class Singleton {
	private static Singleton instance = new Singleton();// 在內部產生本類的例項化物件

	public static Singleton getInstance() { // 通過靜態方法返回instance物件
		return instance;
	}

	private Singleton() { // 將構造方法封裝為私有化
	}

	public void print() {
		System.out.println("Hello World!!!");
	}
}

public class SingletonDemo {
	public static void main(String args[]) {
		Singleton s1 = null; // 宣告物件
		Singleton s2 = null; // 宣告物件
		Singleton s3 = null; // 宣告物件
		s1 = Singleton.getInstance(); // 取得例項化物件
		s2 = Singleton.getInstance(); // 取得例項化物件
		s3 = Singleton.getInstance(); // 取得例項化物件
		s1.print(); // 呼叫方法
		s2.print(); // 呼叫方法
		s3.print(); // 呼叫方法
	}
}

 一、單例模式的介紹
     Singleton是一種建立型模式,指某個類採用Singleton模式,則在這個類被建立後,只可能產生一個例項供外部訪問,並且提供一個全域性的訪問點

二、單例模式的實現

實現的方式有如下四種:

Java程式碼 複製程式碼 收藏程式碼
  1. /**  
  2.  *   
  3.  * 單例模式的實現:餓漢式,執行緒安全 但效率比較低  
  4.  */
  5. publicclass SingletonTest {   
  6. private SingletonTest() {   
  7.     }   
  8. privatestaticfinal SingletonTest instance = new SingletonTest();   
  9. publicstatic SingletonTest getInstancei() {   
  10. return instance;   
  11.     }   
  12. }  
/**
 * 
 * 單例模式的實現:餓漢式,執行緒安全 但效率比較低
 */
public class SingletonTest {

	private SingletonTest() {
	}

	private static final SingletonTest instance = new SingletonTest();

	public static SingletonTest getInstancei() {
		return instance;
	}

}

Java程式碼 複製程式碼 收藏程式碼
  1. /**  
  2.  * 單例模式的實現:飽漢式,非執行緒安全   
  3.  *   
  4.  */
  5. publicclass SingletonTest {   
  6. private SingletonTest() {   
  7.     }   
  8. privatestatic SingletonTest instance;   
  9. publicstatic SingletonTest getInstance() {   
  10. if (instance == null)   
  11.             instance = new SingletonTest();   
  12. return instance;   
  13.     }   
  14. }  
/**
 * 單例模式的實現:飽漢式,非執行緒安全 
 * 
 */
public class SingletonTest {
	private SingletonTest() {
	}

	private static SingletonTest instance;

	public static SingletonTest getInstance() {
		if (instance == null)
			instance = new SingletonTest();
		return instance;
	}
}

Java程式碼 複製程式碼 收藏程式碼
  1. /**  
  2.  * 執行緒安全,但是效率非常低  
  3.  * @author vanceinfo  
  4.  *  
  5.  */
  6. publicclass SingletonTest {   
  7. private SingletonTest() {   
  8.     }   
  9. privatestatic SingletonTest instance;   
  10. publicstaticsynchronized SingletonTest getInstance() {   
  11. if (instance == null)   
  12.             instance = new SingletonTest();   
  13. return instance;   
  14.     }   
  15. }  
/**
 * 執行緒安全,但是效率非常低
 * @author vanceinfo
 *
 */
public class SingletonTest {
	private SingletonTest() {
	}

	private static SingletonTest instance;

	public static synchronized SingletonTest getInstance() {
		if (instance == null)
			instance = new SingletonTest();
		return instance;
	}
}

Java程式碼 複製程式碼 收藏程式碼
  1. /**  
  2.  * 執行緒安全  並且效率高  
  3.  *  
  4.  */
  5. publicclass SingletonTest {   
  6. privatestatic SingletonTest instance;   
  7. private SingletonTest() {   
  8.     }   
  9. publicstatic SingletonTest getIstance() {   
  10. if (instance == null) {   
  11. synchronized (SingletonTest.class) {   
  12. if (instance == null) {   
  13.                     instance = new SingletonTest();   
  14.                 }   
  15.             }   
  16.         }   
  17. return instance;   
  18.     }   
  19. }  

 2.工廠設計模式

       程式在介面和子類之間加入了一個過渡端,通過此過渡端可以動態取得實現了共同介面的子類例項化物件。

      示例程式碼如下:

Java程式碼 複製程式碼 收藏程式碼
  1. interface Animal { // 定義一個動物的介面
  2. publicvoid say(); // 說話方法
  3. }   
  4. class Cat implements Animal { // 定義子類Cat
  5. @Override
  6. publicvoid say() { // 覆寫say()方法
  7.         System.out.println("我是貓咪,喵嗚!");   
  8.     }   
  9. }   
  10. class Dog implements Animal { // 定義子類Dog
  11. @Override
  12. publicvoid say() { // 覆寫say()方法
  13.         System.out.println("我是小狗,汪汪!");   
  14.     }   
  15. }   
  16. class Factory { // 定義工廠類
  17. publicstatic Animal getInstance(String className) {   
  18.         Animal a = null// 定義介面物件
  19. if ("Cat".equals(className)) { // 判斷是哪個子類的標記
  20.             a = new Cat(); // 通過Cat子類例項化介面
  21.         }   
  22. if ("Dog".equals(className)) { // 判斷是哪個子類的標記
  23.             a = new Dog(); // 通過Dog子類例項化介面
  24.         }   
  25. return a;   
  26.     }   
  27. }   
  28. publicclass FactoryDemo {   
  29. publicstaticvoid main(String[] args) {   
  30.         Animal a = null// 定義介面物件
  31.         a = Factory.getInstance(args[0]); // 通過工廠獲取例項
  32. if (a != null) { // 判斷物件是否為空
  33.             a.say(); // 呼叫方法
  34.         }   
  35.     }   
  36. }  
interface Animal { // 定義一個動物的介面
	public void say(); // 說話方法
}

class Cat implements Animal { // 定義子類Cat
	@Override
	public void say() { // 覆寫say()方法
		System.out.println("我是貓咪,喵嗚!");
	}
}

class Dog implements Animal { // 定義子類Dog

	@Override
	public void say() { // 覆寫say()方法
		System.out.println("我是小狗,汪汪!");
	}
}

class Factory { // 定義工廠類
	public static Animal getInstance(String className) {
		Animal a = null; // 定義介面物件
		if ("Cat".equals(className)) { // 判斷是哪個子類的標記
			a = new Cat(); // 通過Cat子類例項化介面
		}
		if ("Dog".equals(className)) { // 判斷是哪個子類的標記
			a = new Dog(); // 通過Dog子類例項化介面
		}
		return a;
	}
}

public class FactoryDemo {

	public static void main(String[] args) {
		Animal a = null; // 定義介面物件
		a = Factory.getInstance(args[0]); // 通過工廠獲取例項
		if (a != null) { // 判斷物件是否為空
			a.say(); // 呼叫方法
		}
	}
}

 3.代理設計模式

       指由一個代理主題來操作真實主題,真實主題執行具體的業務操作,而代理主題負責其他相關業務的處理。比如生活中的通過代理訪問網路,客戶通過網路代理連線網路(具體業務),由代理伺服器完成使用者許可權和訪問限制等與上網相關的其他操作(相關業務)。

      示例程式碼如下:

Java程式碼 複製程式碼 收藏程式碼
  1. interface Network { // 定義Network介面
  2. publicvoid browse(); // 定義瀏覽的抽象方法
  3. }   
  4. class Real implements Network { // 真實的上網操作
  5. publicvoid browse() { // 覆寫抽象方法
  6.         System.out.println("上網瀏覽資訊!");   
  7.     }   
  8. }   
  9. class Proxy implements Network { // 代理上網
  10. private Network network;   
  11. public Proxy(Network network) {// 設定代理的真實操作
  12. this.network = network; // 設定代理的子類
  13.     }   
  14. publicvoid check() { // 身份驗證操作
  15.         System.out.println("檢查使用者是否合法!");   
  16.     }   
  17. publicvoid browse() {   
  18. this.check(); // 呼叫具體的代理業務操作
  19. this.network.browse(); // 呼叫真實的上網操作
  20.     }   
  21. }   
  22. publicclass ProxyDemo {   
  23. publicstaticvoid main(String args[]) {   
  24.         Network net = null// 定義介面物件
  25.         net = new Proxy(new Real()); // 例項化代理,同時傳入代理的真實操作
  26.         net.browse(); // 呼叫代理的上網操作
  27.     }   
  28. }  
interface Network { // 定義Network介面
	public void browse(); // 定義瀏覽的抽象方法
}

class Real implements Network { // 真實的上網操作
	public void browse() { // 覆寫抽象方法
		System.out.println("上網瀏覽資訊!");
	}
}

class Proxy implements Network { // 代理上網
	private Network network;

	public Proxy(Network network) {// 設定代理的真實操作
		this.network = network; // 設定代理的子類
	}

	public void check() { // 身份驗證操作
		System.out.println("檢查使用者是否合法!");
	}

	public void browse() {
		this.check(); // 呼叫具體的代理業務操作
		this.network.browse(); // 呼叫真實的上網操作
	}
}

public class ProxyDemo {
	public static void main(String args[]) {
		Network net = null; // 定義介面物件
		net = new Proxy(new Real()); // 例項化代理,同時傳入代理的真實操作
		net.browse(); // 呼叫代理的上網操作
	}
}

 4.觀察者設計模式

       所謂觀察者模式,舉個例子現在許多購房者都密切觀察者房價的變化,當房價變化時,所有購房者都能觀察到,以上的購房者屬於觀察者,這便是觀察者模式。

       java中可以藉助Observable類和Observer介面輕鬆實現以上功能。當然此種模式的實現也不僅僅侷限於採用這兩個類。

       示例程式碼如下:

Java程式碼 複製程式碼 收藏程式碼
  1. import java.util.Observable;   
  2. import java.util.Observer;   
  3. class House extends Observable {   
  4. privatefloat price;   
  5. publicvoid setPrice(float price) {   
  6. this.setChanged();// 設定變化點
  7. this.notifyObservers(price);// 通知所有觀察者價格改變
  8. this.price = price;   
  9.     }   
  10. publicfloat getPrice() {   
  11. returnthis.price;   
  12.     }   
  13. public House(float price) {   
  14. this.price = price;   
  15.     }   
  16. public String toString() {   
  17. return"房子價格為: " + this.price;   
  18.     }   
  19. }   
  20. class HousePriceObserver implements Observer {   
  21. private String name;   
  22. public HousePriceObserver(String name) {   
  23. super();   
  24. this.name = name;   
  25.     }   
  26. @Override
  27. publicvoid update(Observable o, Object arg) {// 只要改變了 observable 物件就呼叫此方法
  28. if (arg instanceof Float) {   
  29.             System.out.println(this.name + "觀察的價格更改為:"
  30.                     + ((Float) arg).floatValue());   
  31.         }   
  32.     }   
  33. }   
  34. publicclass ObserDeom {   
  35. publicstaticvoid main(String[] args) {   
  36.         House h = new House(1000000);   
  37.         HousePriceObserver hpo1 = new HousePriceObserver("購房者A");   
  38.         HousePriceObserver hpo2 = new HousePriceObserver("購房者B");   
  39.         HousePriceObserver hpo3 = new HousePriceObserver("購房者C");   
  40.         h.addObserver(hpo1);// 給房子註冊觀察者
  41.         h.addObserver(hpo2);// 給房子註冊觀察者
  42.         h.addObserver(hpo3);// 給房子註冊觀察者
  43.         System.out.println(h);// 輸出房子價格
  44. // 修改房子價格,會觸發update(Observable o, Object arg)方法通知購房者新的房價資訊
  45.         h.setPrice(2222222);// 
  46.         System.out.println(h);// 再次輸出房子價格
  47.     }   
  48. }  
import java.util.Observable;
import java.util.Observer;

class House extends Observable {
	private float price;

	public void setPrice(float price) {
		this.setChanged();// 設定變化點
		this.notifyObservers(price);// 通知所有觀察者價格改變
		this.price = price;
	}

	public float getPrice() {
		return this.price;
	}

	public House(float price) {
		this.price = price;
	}

	public String toString() {
		return "房子價格為: " + this.price;
	}
}

class HousePriceObserver implements Observer {
	private String name;

	public HousePriceObserver(String name) {
		super();
		this.name = name;
	}

	@Override
	public void update(Observable o, Object arg) {// 只要改變了 observable 物件就呼叫此方法
		if (arg instanceof Float) {
			System.out.println(this.name + "觀察的價格更改為:"
					+ ((Float) arg).floatValue());
		}

	}

}

public class ObserDeom {
	public static void main(String[] args) {
		House h = new House(1000000);
		HousePriceObserver hpo1 = new HousePriceObserver("購房者A");
		HousePriceObserver hpo2 = new HousePriceObserver("購房者B");
		HousePriceObserver hpo3 = new HousePriceObserver("購房者C");
		h.addObserver(hpo1);// 給房子註冊觀察者
		h.addObserver(hpo2);// 給房子註冊觀察者
		h.addObserver(hpo3);// 給房子註冊觀察者
		System.out.println(h);// 輸出房子價格
		// 修改房子價格,會觸發update(Observable o, Object arg)方法通知購房者新的房價資訊
		h.setPrice(2222222);// 
		System.out.println(h);// 再次輸出房子價格
	}
}

 5.介面卡模式

        如果一個類要實現一個具有很多抽象方法的介面,但是本身只需要實現介面中的部分方法便可以達成目的,所以此時就需要一箇中間的過渡類,但此過渡類又不希望直接使用,所以將此類定義為抽象類最為合適,再讓以後的子類直接繼承該抽象類便可選擇性的覆寫所需要的方法,而此抽象類便是介面卡類。

      示例程式碼如下:

Java程式碼 複製程式碼 收藏程式碼
  1. interface Window {// 定義Window視窗介面,表示視窗操作
  2. publicvoid open();// 視窗開啟
  3. publicvoid close();// 視窗關閉
  4. publicvoid iconified();// 視窗最小化
  5. publicvoid deiconified();// 視窗恢復
  6. publicvoid activated();// 視窗活動
  7. }   
  8. // 定義抽象類實現介面,在此類中覆寫方法,但是所有的方法體為空
  9. abstractclass WindowAdapter implements Window {   
  10. publicvoid open() {   
  11.     };// 視窗開啟
  12. publicvoid close() {   
  13.     };// 視窗關閉
  14. publicvoid iconified() {   
  15.     };// 視窗最小化
  16. publicvoid deiconified() {   
  17.     };// 視窗恢復
  18. publicvoid activated() {   
  19.     };// 視窗活動
  20. }   
  21. // 子類繼承WindowAdapter抽象類,選擇性實現需要的方法
  22. class WindowImpl extends WindowAdapter {   
  23. publicvoid open() {   
  24.         System.out.println("視窗開啟");// 實現open()方法
  25.     }   
  26. publicvoid close() {   
  27.         System.out.println("視窗關閉");// 實現close()方法
  28.     }   
  29. }   
  30. publicclass AdapterDemo {   
  31. publicstaticvoid main(String args[]) {   
  32.         Window win = new WindowImpl(); // 實現介面物件
  33. // 呼叫方法
  34.         win.open();   
  35.         win.close();   
  36.     }   
  37. }  
interface Window {// 定義Window視窗介面,表示視窗操作
	public void open();// 視窗開啟

	public void close();// 視窗關閉

	public void iconified();// 視窗最小化

	public void deiconified();// 視窗恢復

	public void activated();// 視窗活動
}

// 定義抽象類實現介面,在此類中覆寫方法,但是所有的方法體為空
abstract class WindowAdapter implements Window {
	public void open() {
	};// 視窗開啟

	public void close() {
	};// 視窗關閉

	public void iconified() {
	};// 視窗最小化

	public void deiconified() {
	};// 視窗恢復

	public void activated() {
	};// 視窗活動
}

// 子類繼承WindowAdapter抽象類,選擇性實現需要的方法
class WindowImpl extends WindowAdapter {
	public void open() {
		System.out.println("視窗開啟");// 實現open()方法
	}

	public void close() {
		System.out.println("視窗關閉");// 實現close()方法
	}
}

public class AdapterDemo {
	public static void main(String args[]) {
		Window win = new WindowImpl(); // 實現介面物件
		// 呼叫方法
		win.open();
		win.close();
	}
}

 ----------------------------------------------------------------

初學水平有限,錯誤之處難免,覽者勿諷!

參考資料:java開發實戰經典。

------------------------------------------------------------------------------------

PART A:前言

平常我們都在敲程式碼,為了要實現一些我們希望看到的功能,敲一大堆一大堆。往往就會忽略了這樣的一個問題。

你會問敲程式碼就讓我們老老實實的敲程式碼吧,為什麼要那麼麻煩的去考慮那麼多?當然了現在這樣一說你肯定會回答我們肯定不可能就一心只會死頭死腦的無腦敲程式碼啊。是吧?那麼我們還要考慮一些什麼事情呢?這麼跟大家說吧,我們現在敲程式碼做專案就像做房子,現在我們做的事情是,一塊一塊的不斷的壘磚塊,無腦壘。而不管他壘的好不好看美不美觀,也不管他消耗的磚塊是否太多。是不是?再打個比方,從小學起我們就開始拿著筆寫作文。剛剛開始那個時候,還記得自己是怎麼寫作文的麼?是不是照著課本寫?又或者就是寫一些流水賬似的東西?記得那個時候能夠記兩筆流水賬已經能夠讓自己激動不已了是吧?呵呵。那你還記得是從什麼時候開始,老師開始給你講文章的結構文章的排篇佈局,開始給你介紹各種諸如開門見山等等的文章寫法的?今天就讓我們回到那個時候。

接下來我們開始接觸一些比較常用的java設計模式。

PART B:

         B-1工廠模式

你可以從網上找到許許多多關於這個(java設計模式)的文件與資料,如果你下載過看過不止四五份你就會發現,雖然他們的說法都有自己的一套,但是總是有千人一面的地方。而我要告訴你的是,這一面,就是你所需要的東西了。

對於工廠模式而言,每個人都會有自己的體會與看法。就比如有的人說他是將程式碼按照其功能模組化了,也有人說他就是一個分配機制,好比把不同的工作交給不同的人去做一樣,將物件的功能的實現交給一些特製的類去完成,等等等等。只要是接觸過的人,就可以說出一種他的立場上看到的工廠模式。

但是在這裡我要告訴你的是,工廠模式他的關鍵是:將建立物件和使用物件分開。在這樣的一個過程中不僅僅達到了理清編寫者自己思路的作用,也使得程式碼脈絡更加清晰明朗,簡潔易懂。不知道大家還記不記得曾經講哈夫曼樹的時候那棵充斥我們一個多禮拜的哈夫曼樹?我想說,現在這棵樹是沒了,但是重新出現了一座龐大的工廠……在這個工廠裡邊分工明確權責分明,他的每一個子工廠都只負責生產某一種特別的產品,而每一種產品也對應著每一個子工廠的生產線。現在只要想編寫一個程式,就不知道絕的先考慮將它“工廠化”,將它的每一個步驟每一個功能先大卸八塊的區分清楚,然後才開始程式碼的實際編寫工作……

好了,閒話就不多說了,下面我們就通過例項來講講什麼是建立物件和使用物件分開。

(例)

比如我想造一輛寶馬車並讓它跑起來,以前我們都是寫一個寶馬車的類然後直接在這個類裡邊例項化一個他的物件,完了以後緊接著在下邊寫寶馬車的跑的方法,是吧?但是工廠模式不這麼做,工廠模式怎麼做呢?請看下面的步驟:

1.寫一個車的介面,並在裡邊定義一個車的go()方法:

Java程式碼 複製程式碼 收藏程式碼
  1. public interface Car {   
  2.     public void go();   
  3. }  
public interface Car {	public void go();}

 2.寫一個寶馬車的類,讓他去繼承上面這個車的總介面,並且實現裡邊的方法:

Java程式碼 複製程式碼 收藏程式碼
  1. public class BMW implements Car{   
  2.     public void go() {   
  3.     }   
  4. }  
public class BMW implements Car{	public void go() {	}}

 3.是不是少了什麼?呵呵你有車的介面和實現類了當然得有造車工廠咯,是吧?於是我們同樣給它定義一個造車工廠總介面以及一個繼承並且實現它的寶馬造車工廠:

Java程式碼 複製程式碼 收藏程式碼
  1. public interface CarFactory {   
  2.     public Car build(String name) ;   
  3. }  
public interface CarFactory {	public Car build(String name) ;}
Java程式碼 複製程式碼 收藏程式碼
  1. public class BMWFactory implements CarFactory{   
  2.  private static  BMWFactory ins;   
  3.      public static BMWFactory getIns(){   
  4.          if(null==ins){   
  5.              ins=new BMWFactory();   
  6.          }   
  7.          return ins;   
  8.      }   
  9.      BMWFactory(){}   
  10.     public Car build(String name) {   
  11.          if(name.equals("BMW")){   
  12.              return new BMW();   
  13.          }   
  14.         return null;   
  15.     }   
  16. }  
public class BMWFactory implements CarFactory{	 private static  BMWFactory ins;	 	 public static BMWFactory getIns(){		 if(null==ins){			 ins=new BMWFactory();		 }		 return ins;	 }	 	 BMWFactory(){}	 		public Car build(String name) {				 if(name.equals("BMW")){						 return new BMW();		 }				return null;	}}

 4.有的人就會有點牢騷了,我不想老是自己跑工廠去,那樣多麻煩!是吧?好,那麼我們就給他寫一個且車代理商:

Java程式碼 複製程式碼 收藏程式碼
  1. public class AgentFactor {   
  2.     private static AgentFactor ins;   
  3.     public static AgentFactor getIns(){   
  4.         if(ins==null){   
  5.             ins=new AgentFactor();   
  6.         }   
  7.         return ins;   
  8.     }   
  9.     //取得制定品牌 的汽車   
  10.     public CarFactory getCarFactor(String Name){   
  11.         if(Name.equals("BMW")){   
  12.             return new BMWFactory();   
  13.         }   
  14.         return null;   
  15.     }   
  16. }  
public class AgentFactor {	private static AgentFactor ins;	public static AgentFactor getIns(){		if(ins==null){			ins=new AgentFactor();		}		return ins;	}		//取得制定品牌 的汽車	public CarFactory getCarFactor(String Name){		if(Name.equals("BMW")){			return new BMWFactory();		}		return null;	}}

5.好了,車有了,造車工廠有了,連代理商都給你搞定了,那麼就讓我們來寫個主函式讓我們的寶馬車跑起來吧!

Java程式碼 複製程式碼 收藏程式碼
  1. public class CarTest {   
  2.     public void driver(){   
  3.         CarFactory ic=AgentFactor.getIns().getCarFactor("BMW");   
  4.         Car mini=ic.build("MINI");   
  5.         mini.go();   
  6.     }   
  7. }  
public class CarTest {	public void driver(){				CarFactory ic=AgentFactor.getIns().getCarFactor("BMW");		Car mini=ic.build("MINI");		mini.go();	}}

 當然了,也不是真的就讓上面的程式碼跑起來,細心如你,肯定會發現上面的這幾行程式碼是跑不起來的,是不是?具體是為什麼呢,哈哈就留給你咯!

雖然上面給大家的幾行程式碼不能夠直接跑起來,但是通過他們,我想大家對於工廠模式這個概念應該會有一個比較清晰的把握了吧。再次說一遍:工廠模式,就是將物件的建立與使用分開。這樣做的目的,自己開動腦經咯~

B-2 事件監聽模式

相信大家接觸java以來就一直在跟滑鼠監聽器等等各種事件監聽器打交道,對於這些個零零總總的各式各樣的監聽器也並不陌生吧?但是對於這些滑鼠監聽器啊鍵盤監聽器啊什麼的,他的具體的實現方式是怎麼樣的你是否清楚呢?如果你是一個足夠細心而好學的人,那麼我接下來要說的東西對你來說可能是沒什麼必要的了,因為你肯定看過這些監聽器它的原始碼,也必然知道他的執行機制與原理了。

下面讓我們用程式碼例項來看一看這事件監聽的原型吧!

(例)在做通訊的時候我們曾經做過收到訊息並且讓他顯示在一個JTEXTAREA上面,但是若我想要讓他顯示在JLABEL上的話就得對程式碼進行一些聯動的改動,很是麻煩。我們且看事件監聽模式怎麼解決這個問題:

1.寫一個訊息的介面,在裡邊定義幾項訊息的基本屬性:

Java程式碼 複製程式碼 收藏程式碼
  1. //定義一個訊息介面,所有的訊息都是他的實現類   
  2. public interface Msg {   
  3.     public byte getType();//返回訊息型別   
  4.     public String getText();//返回訊息內容   
  5. }  
//定義一個訊息介面,所有的訊息都是他的實現類public interface Msg {	public byte getType();//返回訊息型別	public String getText();//返回訊息內容}

 2.寫一個具體的訊息類,繼承訊息介面:

Java程式碼 複製程式碼 收藏程式碼
  1. public class TextMsg implements Msg{   
  2.     private String text;   
  3.     //具體的訊息類,繼承訊息介面   
  4.     public TextMsg(String text){   
  5.         this.text=text;   
  6.     }   
  7.     public String getText() {   
  8.         return this.text;   
  9.     }   
  10. public byte getType() {   
  11.         return 2;   
  12.     }   
  13. }  
public class TextMsg implements Msg{	private String text;	//具體的訊息類,繼承訊息介面	public TextMsg(String text){		this.text=text;	}	public String getText() {				return this.text;	}public byte getType() {		return 2;	}}

 3.第三布我們要做的是,編寫一個監聽器介面:

Java程式碼 複製程式碼 收藏程式碼
  1. //處理器介面定義   
  2. public interface MsgProcess {   
  3.     //具體的處理器,所有的處理器實現類都必須實現這個方法   
  4.      void processMsg(Msg msg);   
  5. }  
//處理器介面定義public interface MsgProcess {	//具體的處理器,所有的處理器實現類都必須實現這個方法	 void processMsg(Msg msg);}

 4.編寫你需要的監聽器,比如你想讓訊息呈現在JLABEL上:

Java程式碼 複製程式碼 收藏程式碼
  1. import javax.swing.JLabel;   
  2. public class JLabelProcess extends JLabel implements MsgProcess{   
  3.     public void processMsg(Msg msg) {   
  4.         String t=msg.getText();   
  5.         this.setText(t);   
  6.         System.out.println(t);   
  7.     }   
  8. }  
import javax.swing.JLabel;public class JLabelProcess extends JLabel implements MsgProcess{	public void processMsg(Msg msg) {		String t=msg.getText();		this.setText(t);				System.out.println(t);	}}

如果你還想讓訊息顯示在其他地方,比如,JBUTTON上,你可以另外寫一個監聽器的類繼承上面的監聽器介面: 

Java程式碼 複製程式碼 收藏程式碼
  1. import javax.swing.JButton;   
  2. public class JButtonProcess extends JButton implements MsgProcess{   
  3.     public void processMsg(Msg msg) {   
  4.         String t=msg.getText();   
  5.         this.setText(t);   
  6.     }   
  7. }  
import javax.swing.JButton;public class JButtonProcess extends JButton implements MsgProcess{	public void processMsg(Msg msg) {		String t=msg.getText();		this.setText(t);	}}

 5.編寫一個執行緒,我們將模擬生成訊息(事件源)放在這個執行緒裡邊來做:

Java程式碼 複製程式碼 收藏程式碼
  1. public class NetConn extends Thread{   
  2.     //儲存事件監聽器的佇列   
  3.     ArrayList<MsgProcess>  ips=new ArrayList<MsgProcess>();   
  4.     public void addMsgProcess(MsgProcess p){   
  5.         ips.add(p);   
  6.     }   
  7.     public void run(){   
  8.         //模擬事件源   
  9.         int i=0;   
  10.         while(true){   
  11.             Msg s=new TextMsg("我收到的訊息是:"+i);   
  12.             i++;   
  13.             for(int t=0;t<ips.size();t++){   
  14.                 MsgProcess pro=ips.get(t);   
  15.                 pro.processMsg(s);   
  16.             }   
  17.             try {   
  18.                 this.sleep(1000);   
  19.             } catch (InterruptedException e) {e.printStackTrace();}   
  20.         }   
  21.     }   
  22. }  
public class NetConn extends Thread{		//儲存事件監聽器的佇列	ArrayList<MsgProcess>  ips=new ArrayList<MsgProcess>();		public void addMsgProcess(MsgProcess p){		ips.add(p);	}		public void run(){		//模擬事件源		int i=0;		while(true){						Msg s=new TextMsg("我收到的訊息是:"+i);			i++;			for(int t=0;t<ips.size();t++){				MsgProcess pro=ips.get(t);				pro.processMsg(s);			}			try {				this.sleep(1000);			} catch (InterruptedException e) {e.printStackTrace();}		}	}		}

 6.好的,做完了上面的這些工作,接下來就讓我們來寫一個主函式吧:

Java程式碼 複製程式碼 收藏程式碼
  1. import java.awt.FlowLayout;   
  2. import javax.swing.JFrame;   
  3. public class Main {   
  4.     public static void main(String srga[]){   
  5.         NetConn nc=new NetConn();   
  6.         nc.start();   
  7.         JLabelProcess lp=new JLabelProcess();   
  8.         nc.addMsgProcess(lp);   
  9.         JButtonProcess tp=new JButtonProcess();   
  10.         nc.addMsgProcess(tp);   
  11.         JFrame jf=new JFrame("test");   
  12.         jf.add(tp);   
  13.         jf.setSize(300,300);   
  14.         jf.setLayout(new FlowLayout());   
  15.         jf.add(lp);   
  16.         jf.setVisible(true);   
  17.         jf.setDefaultCloseOperation(3);   
  18.     }   
  19. }  
import java.awt.FlowLayout;import javax.swing.JFrame;public class Main {	public static void main(String srga[]){		NetConn nc=new NetConn();		nc.start();				JLabelProcess lp=new JLabelProcess();		nc.addMsgProcess(lp);		JButtonProcess tp=new JButtonProcess();		nc.addMsgProcess(tp);				JFrame jf=new JFrame("test");				jf.add(tp);				jf.setSize(300,300);		jf.setLayout(new FlowLayout());		jf.add(lp);		jf.setVisible(true);		jf.setDefaultCloseOperation(3);	}}

 事件監聽模式介紹到這裡你是不是心裡隱隱感覺,這個世界上的好多事情都變成了一個個事件源和一個個監聽處理器了?如果對於事件監聽模式還有一些不解或者困惑,請細心看上面提供的程式碼示例,慢慢體會它裡邊所蘊含的一些東西,相信你會獲得意想不到的收穫的!

B-3單例模式

好了,說完了兩種比較羅嗦一點的工廠和事件監聽模式,下面讓我們來看看一種比較簡單的java設計模式:單例模式。對於單例模式我想我不用說大家也能夠說出這種模式就是實現單例項的,沒錯,就是如此!

單例就是:保證一個類僅有一個例項,僅提供一個訪問它的全域性訪問點。

他的適用性在於:

 1.當類只能有一個例項而且客戶可以從一個眾所周知的訪問點訪問它時。

 2.當這個唯一例項應該是通過子類化可擴充套件的,並且客戶應該無需更改程式碼就能使用一個擴充套件的例項時。

話不多說,請君看我程式碼示例:

Java程式碼 複製程式碼 收藏程式碼
  1. public class Singleton {   
  2.     private static Singleton sing;   
  3.     private Singleton() {   
  4.     }   
  5.     public static Singleton getInstance() {   
  6.         if (sing == null) {   
  7.