(說明:本內容由網上視頻教程整理,主要是方便自用,僅做參考。若是有錯歡迎指出!) java
簡單工廠模式屬於類的建立型模式,又叫作靜態工廠方法模式。經過專門定義一個類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。 安全
簡介: app
和簡單工廠模式差很少,都是「工廠模式」。 性能
工廠方法模式一樣屬於類的建立型模式又被稱爲多態工廠模式。工廠方法模式的意義是定義一個建立產品對象的工廠接口,將實際建立工做推遲到子類當中。核心工廠類再也不負責產品的建立,這樣核心類成爲一個抽象工廠角色,僅負責具體工廠子類必須實現的接口,這樣進一步抽象化的好處是使得工廠方法模式可使系統在不修改具體工廠角色的狀況下引進新的產品。 ui
「開放和封閉原則」 spa
開放:系統無限擴展; 線程
封閉:不要修改既有代碼。 code
簡單工廠模式破壞了「開放和封閉原則」,好比,若是FruitFactory類是這樣寫: orm
public class FruitFactory { // 簡單工廠,獲取類實例的方法二: // 這個方法的好處是參數名能夠不分大小寫(並且獲取參數能夠隨便處理) // 缺點是增長水果的時候要增長if...else...不易擴展。 public static FruitInter getFruit2(String type){ if(type.equalsIgnoreCase("apple")){ return new Apple(); //return Apple.class.newInstance() }else if(type.equalsIgnoreCase("banana")){ return new Banana(); //return Banana.class.newInstance(); }else{ System.out.println("no such class!"); return null; } }
那麼,若是增長一個水果類(如Pear.java)的話,就須要增長一個else…的分支語句來處理,這就破壞了「開放和封閉原則」。 視頻
使用工廠方法模式:建立一個抽象工廠(或者說接口)FruitFactory.java,內部聲明一個方法getFruit()方法;而後爲每一個水果類分別建立本身的工廠類,如AppleFactory.java,並實現FruitFactory接口,在實現的getFruit()方法中完成類的實例操做。
【具體作法:】
首先,Apple.java、Banana.java、Fruit.java三個類都和簡單工廠類相同:
public interface Fruit { public void get(); } public class Apple implements Fruit { public void get(){ System.out.println("Collect apple."); } } public class Banana implements Fruit{ public void get() { System.out.println("Collect banana."); } }
其次,增長抽象工廠類(接口):
public interface FruitFactory { public Fruit getFruit(); }
而後,爲Apple.java、Banana.jav a提供工廠類:
public class AppleFactory implements FruitFactory { public Fruit getFruit() { return new Apple(); } } public class BananaFactory implements FruitFactory { public Fruit getFruit() { return new Banana(); } }
main方法中這麼寫:
public class MainClass { public static void main(String[] args) { // Apple FruitFactory fruitFactory1 = new AppleFactory(); Fruit apple = fruitFactory1.getFruit(); apple.get(); // Banana FruitFactory fruitFactory2 = new BananaFactory(); Fruit banana = fruitFactory2.getFruit(); banana.get(); } }
通常的思惟是,直接在main方法中實現全部的業務,以下所示:
public class Main { public static void main(String[]args){ System.out.println("---Caculation Program---"); System.out.print("Input the first num: "); Scanner scanner = new Scanner(System.in); String num1 = scanner.nextLine(); System.out.print("Input the operation: "); String oper = scanner.nextLine(); System.out.println("Input the second num: "); String num2 = scanner.nextLine(); double num1d = Double.parseDouble(num1); double num2d = Double.parseDouble(num2); double result = 0; if(oper.equals("+")){ result = num1d + num2d; }else if(oper.equals("-")){ result = num1d - num2d; }else{ System.out.println("ERROR!"); System.exit(0); } System.out.println("Result is: "+result); } }
這樣的代碼冗餘、可擴展性很差!
下面使用工廠模式實現。
即便用專用的類(工廠類)來獲取操做類(Operation類,用來實現各自的不一樣的四則運算)
增長抽象工廠(接口):
單例模式是一種對象建立型模式,使用單例模式,能夠保證爲一個類只生成惟一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。
其實,GoF對單例模式的定義是:保證一個類、只有一個實例存在,同時提供能對該實例加以訪問的全局訪問方法。
在應用系統開發中,咱們經常有如下需求:
l 在多個線程之間,好比servlet環境,共享同一個資源或者操做同一個對象;
l 在整個程序空間使用全局變量,共享資源;
l 大規模系統中,爲了性能的考慮,須要節省對象的建立時間等等。
由於Singleton模式能夠保證爲一個類只生成惟一的實例對象,因此這些狀況,Singleton模式就派上用場了。
像上面定義的類,外面的獲取到的Person對象只會有一個。
在懶漢式中,咱們將Synchronized加在了整個方法前,因此一個線程會守住整個方法,這樣就影響了效率,咱們是但願person只被實例化一次,能夠將Synchronized加在實例化前:
這裏還有個問題,就是當兩個線程同時進入if的話,那麼還會建立兩個對象,下面加上兩重循環:
以上就是「雙重檢查」!
雙重檢查比懶漢式的效率更高:由於若是有多個線程同時執行的時候,不會讓其餘線程等待(僅第一次執行的時候可能會等待,之後都不會等待)!
對於餓漢式,餓漢式優勢是簡單且線程永遠安全,可是比較耗費資源,由於只要類被加載就對象就被建立。
Prototype模式是一種對象建立型模式,它採起復制原型對象的方法來建立對象的實例。使用Prototype模式建立的實例,具備與原型同樣的數據。
1) 由原型對象自身建立目標對象。也就是說,對象建立這一動做發自原型對象自己;
2) 目標對象是原型對象的一個克隆。也就是說,經過Prototype模式建立的對象,不只僅與原型對象具備相同的結構,還與原型對象具備相同的值;
3) 根據對象克隆深度層次的不一樣,有淺度克隆與深度克隆;
4) 要想類可以被克隆,就必須讓類實現Cloneable接口(其實僅僅是作一個聲明而已!)。
假如,Person類裏有屬性:List<String>friends,即:
由於person1的屬性friends持有的是另一個對象的引用,因此在main方法中克隆的時候,(在棧中)person2克隆的也是一個引用,且指向同一個對象:
這就是「淺拷貝」,要想friends指向的也是全新的對象,那麼就要手動添加(即「深拷貝」):