《設計模式——java版》(二)
阿新 • • 發佈:2018-12-21
第三章 建立型模式簡介
一、單例模式
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();
}
}