1. 程式人生 > >《設計模式——java版》(二)

《設計模式——java版》(二)

第三章  建立型模式簡介

一、單例模式 

         1. 意思是:確保一個類只有一個例項,而且自行例項化並向整個系統提供這個例項

         2. 適用場景:建立目錄、資料庫連線等需要單執行緒操作的場合,用於實現對系統資源的控制。

         3.分類:餓漢式:類載入的時候就進行物件例項化
                       懶漢式:第一次引用類時,才進行物件例項化

                    3.1餓漢式(執行緒安全)

public class Singleton {
	//1. 構造方法私有化,外部就無法建立多個例項***重要
	private Singleton(){}
	//2. 建立類的唯一例項,用static來修飾,可以直接用類名來獲取例項
	private static Singleton instance = new Singleton();
	//3. 提供一個獲取例項的方法
	
	public static Singleton getInstance(){
		return instance;
	}
}
                         由於建構函式是私有的,因此不能被繼承。

                     3.2懶漢式(執行緒不安全)

public class Singleton {
	//1.構造方法私有化
	private Singleton(){}
	//2.宣告類的例項
	private static Singleton instance;
	//3.使用例項的方法
	public static Singleton getInstance(){
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

                      3.3懶漢式(執行緒安全)

public class Singleton2 {
	//1.建構函式私有化

	private Singleton2(){}
	
	//2.宣告類的例項
	private static Singleton2 instance;
	
	//3.獲取一個獲得例項的方法
	public static synchronized Singleton2 getInstance(){
		if (instance == null) {
			instance = new Singleton2();
		}
		for (int i = 0; i < 10; i++) {
			System.out.println(i);
		}
		return instance;
	}
}


            4.餓漢式和懶漢式的區別

                    (1)餓漢式在類載入時就被例項化,懶漢式是在類第一被引用時例項化                     (2)從資源利用效率上說,餓漢式要差一些;但從速度和反應時間角度來講,餓漢式單例類則比懶漢式單例類稍好些

            5.單例模式的優缺點

                     優點:                               (1)減少記憶體的開支,特別是一個物件需要頻繁的建立、銷燬時                               (2)由於單例模式只生成一個例項,減少了系統的效能開銷,當一個物件的產生需要比較多資源時,如讀取配置檔案、產生其他依賴物件時,則可以通過                                           在啟用時直接產生一個物件,然後用永久駐留記憶體的方式來解決                               (3)單例模式可以避免對資源的多重佔用,例如一個寫檔案動作,由於只有一個例項存在於記憶體中,避免了對同一資原始檔的同時操作                               (4)單例模式可以在系統設定全域性的訪問點,優化和共享資源訪問,例如,可以設計一個單例類,負責所有資料表的對映處理                      缺點:                               (1)單例模式無法建立子類,擴充套件困難                               (2)單例模式對測試不利                               (3)單例模式與單一職責原則有衝突

             6.適用場景

                          (1)要求生成唯一序列號的場景                           (2)在整個專案中需要一個共享訪問點或共享資料.例如:一個Web頁面上的計數器,可以不用每次重新整理都記錄到資料庫中,使用單例模式保持計數器的值,                                       並確保是執行緒安全的                           (3)建立一個物件需要消耗的資源過多,如訪問IO或資料庫等資源等                           (4)需要定義大量的靜態常量和靜態方法的環境

             7.應用

                          Spring框架中的每個Bean預設就是單例的;Java基礎類庫中的java.lang.Runtime類也採用了單例模式,其getRuntime()方法返回了唯一的例項
/*Created By guolujie 2017年10月16日*/
class NumThread extends Thread{
	private String threadName;
	public NumThread(String name){
		threadName = name;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		Singleton thread1 = Singleton.getInstance();
		for (int i = 0; i < 5; i++) {
			System.out.println(threadName + "第" + thread1.getNum() + "次訪問!");
			try {
				this.sleep(1000);
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}
}
public class test {
	public static void main(String[] args) {
		NumThread numThread1 = new NumThread("執行緒A");
		NumThread numThread2 = new NumThread("執行緒B");
		numThread1.start();
		numThread2.start();
	}
}

                              執行結果:                                                       

二、工廠方法模式

             1.工廠方法模式又叫虛擬建構函式模式或者多型性工廠模式。工廠方法模式的用意是,定義一個建立產品對                    象的工廠介面,將實際建立性工作推遲到子類中。

             2.在工廠方法模式中共涉及以下四個角色:

                    (1)抽象工廠角色:該角色是工廠方法模式的核心,與應用系統無關,任何在建立物件的工廠類必須實現這個介面                     (2)具體工廠角色:該角色實現了抽象工廠介面,含有與應用密切相關的邏輯,並且受到應用程式的呼叫以建立產品物件                     (3)抽象產品角色:該角色負責定義產品的共性,實現對產品最抽象的定義                     (4)具體產品角色:該角色實現抽象產品角色所宣告的介面,工廠方法模式所建立的每一個物件都是某個具體產品角色的例項

             3.抽象工廠程式碼例項

                           3-1抽象工廠Creator.java

public interface Creator {
	/*
	 * 工廠方法
	 * 建立一個產品物件,其輸入引數型別可以自行設定
	 */
	public <T extends Product> T factory(Class<T> c);
}

                           3-2抽象產品Produce.java

public interface Product {
	//產品類的公共方法
	public void method1();
	public void method2();
}

                          3-3具體工廠類ConcreteCreator.java

public class ConcreteCreator implements Creator {
	public <T extends Product> T factory(Class<T> c){
		Product product = null;
		try {
			product = (Product) Class.forName(c.getName()).newInstance();
		} catch (Exception e) {
			// TODO: handle exception
		}
		return (T) product;
	}
}

                          3-4具體產品類ConcreteProduct.java

public class ConcreteProduct implements Product {
	public void method1(){
		//業務邏輯處理程式碼
	}
	public void method2(){
		//業務邏輯處理程式碼
	}
}

                         3-5應用程式碼FactoryMethodDemo.java

public class FactoryMethodDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Creator creator = new ConcreteCreator();
		Product product = creator.factory(ConcreteProduct.class);
		/*
		 * 繼續業務處理
		 */
	}
}



            4.工廠方法模式的優點

                             優點:(1)良好的封裝性,程式碼結構清晰                                         (2)優秀的可擴充套件性                                         (3)遮蔽產品類                                         (4)工廠方法模式是典型的解耦框架

            5.工廠方法模式的適用場景

                              (1)工廠方法模式是new一個物件的替代品,因此在所有需要生成物件的地方都可以使用,會增加程式碼的複雜度                               (2)需要靈活的可擴充套件的框架時,可以考慮採用工廠方法模式                               (3)工廠方法模式可以用到異構專案中                               (4)工廠方法模式可以使用在測試驅動開發的框架下

            6.工廠方法模式的例項

                        
public interface FruitGardener {
	public Fruit factory();
}                 
public interface Fruit {
	public void grow();
}
                  
public class AppleGardener implements FruitGardener {
	public Fruit factory(){
		return new Apple();
	}
}

public class GrapeGardener implements FruitGardener {
	public Fruit factory(){
		return new Grape();
	}
}

public class Apple implements Fruit {
	private int treeAge;

	public int getTreeAge() {
		return treeAge;
	}

	public void setTreeAge(int treeAge) {
		this.treeAge = treeAge;
	}
	public void grow(){
		System.out.println("蘋果正在生長...");
	}
	public void harvest(){
		System.out.println("收穫蘋果");
	}
	public void plant(){
		System.out.println("栽種蘋果");
	}
}
public class Grape implements Fruit {
	private boolean seedless;

	public boolean isSeedless() {
		return seedless;
	}

	public void setSeedless(boolean seedless) {
		this.seedless = seedless;
	}
	public void grow(){
		System.out.println("葡萄正在生長...");
	}
	public void harvest(){
		System.out.println("收穫葡萄");
	}
	public void plant(){
		System.out.println("栽種葡萄");
	}
}

public class ClientDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FruitGardener fruitGardener = new AppleGardener();
		Apple apple = (Apple) fruitGardener.factory();
		apple.plant();
		apple.grow();
		apple.harvest();
		
		fruitGardener = new GrapeGardener();
		Grape grape = (Grape) fruitGardener.factory();
		grape.plant();
		grape.grow();
		grape.harvest();
	}

}