建立型模式,就是建立對象的模式,抽象了實例化的過程。它幫助一個系統獨立於如何建立、組合和表示它的那些對象。關注的是對象的建立,建立型模式將建立對象的過程進行了抽象,也能夠理解爲將建立對象的過程進行了封裝,做爲客戶程序僅僅須要去使用對象,而再也不關心建立對象過程當中的邏輯html
定義:確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。
類圖:java
主要有三個部分:數據庫
私有的構造方法 指向本身實例的私有靜態引用 以本身實例爲返回值的靜態的公有的方法
特色:*
優勢:編程
在內存中只有一個對象,節省內存空間。 避免頻繁的建立銷燬對象,能夠提升性能。 避免對共享資源的多重佔用。 能夠全局訪問。
適用場景:安全
須要頻繁實例化而後銷燬的對象。 建立對象時耗時過多或者耗資源過多,但又常常用到的對象。 有狀態的工具類對象。 頻繁訪問數據庫或文件的對象等等。
注意事項:多線程
只能使用單例類提供的方法獲得單例對象,不要使用反射,不然將會實例化一個新對象。 不要作斷開單例類對象與類中靜態引用的危險操做。 多線程使用單例使用共享資源時,注意線程安全問題。
餓漢式:ide
/** * 一:餓漢式(類加載的時候就建立了實例) * 優勢:實現了線程安全,編寫簡單;執行效率高 * 缺點:初始化就建立了實例,對加載速度和內存有消耗,,因此這種方法要求單例對象初始化速度快且佔用內存小 */ // 一、成員變量靜態化 private static Singleton3 instance = new Singleton3(); //二、構造函數私有化,防止外部實例化 private Singleton3(){} //三、提供公共靜態建立實例方法 public static Singleton3 getInstance(){ return instance; } /** * 二:枚舉類型:根據枚舉類型的特色,實現單例模式所須要的建立單例、線程安全、簡潔的需求 * 優勢:實現比較簡潔,保證了單實例,線程安全 * 缺點:使用枚舉類型,不是很熟悉 */ /** * 枚舉類型的特色: * 一、枚舉類型 = 不可被繼承的類(final): * 枚舉本質上是經過普通類實現的,只是編譯器爲咱們進行了特殊處理 * 每一個枚舉類型都繼承自java.lang.Enum,並自動添加了values(),valueOf() * 枚舉類的實例 = 常量 * 二、每一個枚舉元素 = 類靜態常量 = 1個實例 * 枚舉元素,都是經過靜態代碼來進行初始化,即在類加載期間進行初始化,保證了實例只被建立一次,線程安全 * 獲取枚舉元素 = 獲取實例 * 三、構造方法 訪問權限 默認=私有(private):他的構造器是私有的,底層沒有可供調用的無參數的構造器;防止了其餘人建立實例 * 四、每個枚舉類型&枚舉變量在JVM中都是惟一的: * 即java在序列化和反序列化美劇時作了特殊的規定:枚舉的writeObject(),readObject(),readObjectNoData()等方法是被禁用的,所以不存在序列化接口以後調用readObject會破環單例的問題 * 保證了枚舉元素的不可變行,即不能經過克隆、序列化&反序列化來複制枚舉,即保證了1個枚舉常量=1個實例 即單例 */ public enum Singleton { INSTANCE; public void whateverMethod() { } }
懶漢式:函數
//程序中建立類只有兩種方式:1建立類的一個對象,用該對象去調用類中的方法;2使用類名直接調用類中方法,類名.方法名();單例模式防止外部new對象,只能使用類方法,且是靜態的。 /** * 一:懶漢式(須要的時候建立實例),線程不安全。當多個線程同時訪問時,不能正常工做。 * 優勢:按需加載 * 缺點:線程不安全。多個線程同時訪問時,會建立多個實例。 */ // 一、成員變量靜態化 private static Singleton1 instance; //二、構造函數私有化,防止外部實例化 private Singleton1(){} //三、提供公共靜態建立實例方法 public static Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } /** * 二:懶漢式:線程安全,加同步鎖, * 優勢:實現了線程安全 * 缺點:每次訪問都要進行線程同步(調用synchronized鎖),形成過多的同步開銷(加鎖=耗時、耗能) */ // 一、成員變量靜態化 private static Singleton1 instance; //二、構造函數私有化,防止外部實例化 private Singleton1(){} //三、提供公共靜態建立實例方法 public static synchronized Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } // 一、成員變量靜態化 private static Singleton1 instance; //二、構造函數私有化,防止外部實例化 private Singleton1(){} //三、提供公共靜態建立實例方法 public static Singleton1 getInstance() { synchronized(Singleton.class){ if (instance == null) { instance = new Singleton1(); } } return instance; } /** *三:懶漢式改進—雙重校驗鎖;在同步鎖的基礎上,添加一層if判斷,若單例已經建立,則不須要再執行加鎖操做就能夠獲取實例,從而提升了性能。 *優勢:避免了每次調用都要調用synchronized鎖,同時雙重校驗又保證了線程安全,不會重複建立實例。 * 缺點:較爲複雜,容易出錯 */ // 一、成員變量靜態化 private static Singleton1 instance = null; //二、構造函數私有化,防止外部實例化 private Singleton1(){} //三、提供公共靜態建立實例方法 public static Singleton1 getInstance() { if (instance == null) { synchronized (Singleton1.class) { if (instance == null) { instance = new Singleton1(); } } } return instance; } /** * 四:靜態內部類。在靜態內部類中建立單例,在加載內部類時纔會建立單例 * 優勢:根據靜態內部類的特性,實現了線程安全,按需加載,同時比較簡潔 */ // 一、建立靜態內部類 private static class Singleton2{ // 靜態類裏面建立單例 private static Singleton1 instance = new Singleton1(); } //二、構造函數私有化,防止外部實例化 private Singleton1(){} //三、提供公共靜態建立實例方法 public static Singleton1 getInstance() { //調用靜態類的實例方法 return Singleton2.instance; } /** * 調用過程說明 * 一、外部調用類的getInstance()方法 * 二、getInstance()方法自動調用內部類的方法,實現初始化 * 三、而該類在裝載 & 被初始化時,會初始化他的靜態域,從而建立單例 * 四、因爲是靜態域,所以JVM只會加載一遍,java虛擬機保證了線程安全 * 五、最終實現只建立一個實例。 */
定義:又靜態工廠模式,能夠根據參數的不一樣返回不一樣類的實例。
類圖:工具
由此能夠看出:簡單工廠模式由三部分組成:具體工廠、具體產品和抽象產品性能
工廠類(Creator)角色:擔任這個角色的是簡單工廠模式的核心,含有與應用緊密相關的商業邏輯。工廠類在客戶端的直接調用下建立產品對象,它每每由一個具體Java類實現。 抽象產品(AbstractProduct)角色:擔任這個角色的類是由簡單工廠模式所建立的對象的父類,或它們共同擁有的接口。抽象產品角色能夠用一個Java接口或者Java抽象類實現。 具體產品(ConcreteProduct)角色:簡單工廠模式所建立的任何對象都是這個角色的實例,具體產品角色由一個具體Java類實現。
總結:
簡單工廠只有一個工廠類,經過switch語句來區分建立哪一個產品。 工廠方法模式是擴展了簡單工廠模式,區分爲抽象工廠和具體工廠實現。
定義:定義一個建立對象的工廠接口,讓子類決定實例化哪個類,將實際的建立工做推遲到子類當中。
類圖:
工廠方法模式包含
抽象產品:通常是產品接口或者抽象產品類。主要目的是定義產品的規範,全部的產品實現都必須遵循產品接口定義的規範。產品接口是調用者最爲關心的,產品接口定義的優劣直接決定了調用者代碼的穩定性。 具體產品:實現產品接口的具體類,決定了產品在客戶端中的具體行爲。 抽象工廠:通常是工廠接口或者抽象工廠類。是工廠方法模式的核心,與調用者直接交互用來提供產品。 具體工廠:在編程中,工廠實現決定如何實例化產品,是實現擴展的途徑,須要有多少種產品,就須要有多少個具體的工廠實現。
優缺點:
優勢:(1)封裝了建立產品的方法,用戶無須關心具體實現;(2)添加新產品時,只須要添加具體產品類和具體工廠類(實現或繼承抽象產品、工廠類);(3)將建立工廠方法推遲到子類當中,實現了多態。工廠方法模式也叫多態工廠模式,之因此是多態,由於全部具體工廠類都具備同一父類。 缺點:(1)在添加新產品時,須要添加具體產品類、具體工廠類。當存在較多產品時,致使產品、產品工廠類增多,必定程度上增長了系統的複雜度,更多的類須要編譯和運行,給系統帶來了一些額外的開銷。(2) 因爲考慮到系統的可擴展性,須要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增長了系統的抽象性和理解難度,且在實現時可能須要用到DOM、反射等技術,增長了系統的實現難度。
代碼舉例
//一、抽象產品類 public interface Moveable { public void run(); } //二、具體產品實現類 public class Car implements Moveable { @Override public void run() { System.out.println("小汽車!"); } } public class Plane implements Moveable { @Override public void run() { System.out.println("大飛機!"); } } //三、抽象工廠類 public abstract class Factory { public abstract Moveable create(); } //四、具體工廠實現類 public class CarFactory extends Factory { @Override public Moveable create() { return new Car(); } } public class PlaneFactory extends Factory { @Override public Moveable create() { return new Plane(); } } //測試類 public class FactoryTest { @Test public void FactoryTest(){ Factory car = new CarFactory(); Moveable m = car.create(); // Factory plane = new PlaneFactory(); // Moveable m= plane.create(); m.run(); } }
定義:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
類圖:
能夠看到,抽象工廠模式也是包含抽象產品、具體產品、抽象工廠、具體工廠。
可是抽象工廠中有產品等級結構和產品族的概念。
產品等級結構:產品等級結構即產品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。 產品族:在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不一樣產品等級結構中的一組產品,如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中。
和工廠方法模式的區別:
工廠方法模式提供的是一個產品等級結構的實現,抽象工廠模式提供多個不一樣的產品等級結構的實現。
優缺點:
優勢:能夠在類的內部對產品族進行約束
缺點:產品族擴展比較麻煩。當增長新的產品時,全部的工廠類都要添加其相關代碼。
代碼舉例:
//一、抽象產品類 public abstract class Vehicle{ public abstract void run(); } public abstract class Food { public abstract void printName(); } public abstract class Weapon { public abstract void shoot(); } //二、具體實現類 //第一個產品族 public class Car extends Vehicle { @Override public void run() { System.out.println("小汽車!"); } } public class Apple extends Food{ @Override public void printName() { System.out.println("紅蘋果"); } } public class AK47 extends Weapon { @Override public void shoot() { System.out.println("大火球,huhuhu。。。。。。"); } } //第2個產品族 public class Plane extends Vehicle { @Override public void run() { System.out.println("大灰機"); } } public class Pizza extends Food{ @Override public void printName() { System.out.println("披薩"); } } public class _98K extends Weapon{ @Override public void shoot() { System.out.println("砰砰砰。。。。。。"); } } //三、抽象工廠類 public abstract class AbstractFactory { public abstract Vehicle createVehicle(); public abstract Weapon createWeapon(); public abstract Food createFood(); } //四、具體工廠實現類 public class DefaultFactory extends AbstractFactory{ @Override public Vehicle createVehicle() { return new Car(); } @Override public Weapon createWeapon() { return new AK47(); } @Override public Food createFood() { return new Apple(); } } public class SuperFactory extends AbstractFactory{ @Override public Vehicle createVehicle() { return new Plane(); } @Override public Weapon createWeapon() { return new _98K(); } @Override public Food createFood() { return new Pizza(); } } //五、測試類 public class AbstractFactoryTest { @Test public void abstractFactoryTest(){ // AbstractFactory a = new DefaultFactory(); AbstractFactory a = new SuperFactory(); Vehicle v= a.createVehicle(); v.run(); Weapon w = a.createWeapon(); w.shoot(); Food f= a.createFood(); f.printName(); } }
總結:
定義:將一個複雜對象的構建與它的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
類圖:
建造者模式包含四個要素:
產品類:通常是一個較爲複雜的對象,也就是說建立對象的過程比較複雜,通常會有比較多的代碼量。在本類圖中,產品類是一個具體的類,而非抽象類。實際編程中,產品類能夠是由一個抽象類與它的不一樣實現組成,也能夠是由多個抽象類與他們的實現組成。 抽象建造者:引入抽象建造者的目的,是爲了將建造的具體過程交與它的子類來實現。這樣更容易擴展。通常至少會有兩個抽象方法,一個用來建造產品,一個是用來返回產品。 建造者:實現抽象類的全部未實現的方法,具體來講通常是兩項任務:組建產品;返回組建好的產品。 導演類:負責調用適當的建造者來組建產品,導演類通常不與產品類發生依賴關係,與導演類直接交互的是建造者類。通常來講,導演類被用來封裝程序中易變的部分。
優缺點:
優勢:
將具體的業務邏輯實現封裝在了導演類中,無須知道具體產品類的結構; 當添加新的產品時,只須要實現一個新的建造者類,並添加相應的導演類實現建立具體的產品。
代碼實現:
class Product { private String name; private String type; public void showProduct(){ System.out.println("名稱:"+name); System.out.println("型號:"+type); } public void setName(String name) { this.name = name; } public void setType(String type) { this.type = type; } } abstract class Builder { public abstract void setPart(String arg1, String arg2); public abstract Product getProduct(); } class ConcreteBuilder extends Builder { private Product product = new Product(); public Product getProduct() { return product; } public void setPart(String arg1, String arg2) { product.setName(arg1); product.setType(arg2); } } public class Director { private Builder builder = new ConcreteBuilder(); public Product getAProduct(){ builder.setPart("寶馬汽車","X7"); return builder.getProduct(); } public Product getBProduct(){ builder.setPart("奧迪汽車","Q5"); return builder.getProduct(); } } public class Client { public static void main(String[] args){ Director director = new Director(); Product product1 = director.getAProduct(); product1.showProduct(); Product product2 = director.getBProduct(); product2.showProduct(); } }
與工廠模式的區別:
從結構上看,建造者模式只比工廠模式多了一個「導演類」的角色,若是沒有這個導演類,就相似簡單工廠模式了。
工廠模式是將對象的建立過程封裝在工廠類中,由工廠類向客戶端提供最終的產品。
建造者模式中,建造類通常只提供產品類中各個組件的建造,而將具體的建造過程交由導演類,由導演類實現具體的產品。
因此建造者模式通常用來建立更復雜的對象。
待續。
http://design-patterns.readth...
https://www.w3cschool.cn/java...