設(shè)計(jì)模式(Design Patterns)
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供定西網(wǎng)站建設(shè)、定西做網(wǎng)站、定西網(wǎng)站設(shè)計(jì)、定西網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、定西企業(yè)網(wǎng)站模板建站服務(wù),十余年定西做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
——可復(fù)用面向?qū)ο筌浖幕A(chǔ)
設(shè)
計(jì)模式(Design
pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代
碼可靠性。
毫無疑問,設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的,設(shè)計(jì)模式使代碼編制真正工程化,設(shè)計(jì)模式是軟件工程的基石,如同大廈的一塊塊磚石一樣。項(xiàng)目中合理的運(yùn)用
設(shè)計(jì)模式可以完美的解決很多問題,每種模式在現(xiàn)在中都有相應(yīng)的原理來與之對應(yīng),每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問題,以及該問題的核心解決
方案,這也是它能被廣泛應(yīng)用的原因。
一、設(shè)計(jì)模式的分類
總體來說設(shè)計(jì)模式分為三大類:
創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問者模式、中介者模式、解釋器模式。
其實(shí)還有兩類:并發(fā)型模式和線程池模式。
例子:
單例模式(Singleton)
單例對象(Singleton)是一種常用的設(shè)計(jì)模式。在Java應(yīng)用中,單例對象能保證在一個(gè)JVM中,該對象只有一個(gè)實(shí)例存在。這樣的模式有幾個(gè)好處:
1、某些類創(chuàng)建比較頻繁,對于一些大型的對象,這是一筆很大的系統(tǒng)開銷。
2、省去了new操作符,降低了系統(tǒng)內(nèi)存的使用頻率,減輕GC壓力。
3、有些類如交易所的核心交易引擎,控制著交易流程,如果該類可以創(chuàng)建多個(gè)的話,系統(tǒng)完全亂了。(比如一個(gè)軍隊(duì)出現(xiàn)了多個(gè)司令員同時(shí)指揮,肯定會亂成一團(tuán)),所以只有使用單例模式,才能保證核心交易服務(wù)器獨(dú)立控制整個(gè)流程。
首先我們寫一個(gè)簡單的單例類:
[java] view plaincopy
public class Singleton {
/* 持有私有靜態(tài)實(shí)例,防止被引用,此處賦值為null,目的是實(shí)現(xiàn)延遲加載 */
private static Singleton instance = null;
/* 私有構(gòu)造方法,防止被實(shí)例化 */
private Singleton() {
}
/* 靜態(tài)工程方法,創(chuàng)建實(shí)例 */
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
/* 如果該對象被用于序列化,可以保證對象在序列化前后保持一致 */
public Object readResolve() {
return instance;
}
}
設(shè)計(jì)模式主要分三個(gè)類型:創(chuàng)建型、結(jié)構(gòu)型和行為型。
其中創(chuàng)建型有:
一、Singleton,單例模式:保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)
二、Abstract Factory,抽象工廠:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無須指定它們的具體類。
三、Factory Method,工廠方法:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個(gè)類,F(xiàn)actory Method使一個(gè)類的實(shí)例化延遲到了子類。
四、Builder,建造模式:將一個(gè)復(fù)雜對象的構(gòu)建與他的表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
五、Prototype,原型模式:用原型實(shí)例指定創(chuàng)建對象的種類,并且通過拷貝這些原型來創(chuàng)建新的對象。
行為型有:
六、Iterator,迭代器模式:提供一個(gè)方法順序訪問一個(gè)聚合對象的各個(gè)元素,而又不需要暴露該對象的內(nèi)部表示。
七、Observer,觀察者模式:定義對象間一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知自動更新。
八、Template Method,模板方法:定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中,TemplateMethod使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可以重定義該算法得某些特定步驟。
九、Command,命令模式:將一個(gè)請求封裝為一個(gè)對象,從而使你可以用不同的請求對客戶進(jìn)行參數(shù)化,對請求排隊(duì)和記錄請求日志,以及支持可撤銷的操作。
十、State,狀態(tài)模式:允許對象在其內(nèi)部狀態(tài)改變時(shí)改變他的行為。對象看起來似乎改變了他的類。
十一、Strategy,策略模式:定義一系列的算法,把他們一個(gè)個(gè)封裝起來,并使他們可以互相替換,本模式使得算法可以獨(dú)立于使用它們的客戶。
十二、China of Responsibility,職責(zé)鏈模式:使多個(gè)對象都有機(jī)會處理請求,從而避免請求的送發(fā)者和接收者之間的耦合關(guān)系
十三、Mediator,中介者模式:用一個(gè)中介對象封裝一些列的對象交互。
十四、Visitor,訪問者模式:表示一個(gè)作用于某對象結(jié)構(gòu)中的各元素的操作,它使你可以在不改變各元素類的前提下定義作用于這個(gè)元素的新操作。
十五、Interpreter,解釋器模式:給定一個(gè)語言,定義他的文法的一個(gè)表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來解釋語言中的句子。
十六、Memento,備忘錄模式:在不破壞對象的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài)。
結(jié)構(gòu)型有:
十七、Composite,組合模式:將對象組合成樹形結(jié)構(gòu)以表示部分整體的關(guān)系,Composite使得用戶對單個(gè)對象和組合對象的使用具有一致性。
十八、Facade,外觀模式:為子系統(tǒng)中的一組接口提供一致的界面,fa?ade提供了一高層接口,這個(gè)接口使得子系統(tǒng)更容易使用。
十九、Proxy,代理模式:為其他對象提供一種代理以控制對這個(gè)對象的訪問
二十、Adapter,適配器模式:將一類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些類可以一起工作。
二十一、Decrator,裝飾模式:動態(tài)地給一個(gè)對象增加一些額外的職責(zé),就增加的功能來說,Decorator模式相比生成子類更加靈活。
二十二、Bridge,橋模式:將抽象部分與它的實(shí)現(xiàn)部分相分離,使他們可以獨(dú)立的變化。
二十三、Flyweight,享元模式
23種設(shè)計(jì)模式要在這里詳細(xì)的都說一遍內(nèi)容實(shí)在太多了啊,推薦你一本好書《軟件秘笈:設(shè)計(jì)模式那點(diǎn)事》,里面講解的23中設(shè)計(jì)模式例子很生動,容易理解,還有JDK中設(shè)計(jì)模式應(yīng)用情況,看了收獲挺大的!百度里面搜“設(shè)計(jì)模式”,第一條中設(shè)計(jì)模式百度百科中就有首推該圖書,瀏覽量在20幾萬以上的,不會錯(cuò)的。
祝你早日學(xué)會設(shè)計(jì)模式!
.餓漢式單例類
//餓漢式單例類.在類初始化時(shí),已經(jīng)自行實(shí)例化
public class Singleton1 {
//私有的默認(rèn)構(gòu)造子
private Singleton1() {}
//已經(jīng)自行實(shí)例化
private static final Singleton1 single = new Singleton1();
//靜態(tài)工廠方法
public static Singleton1 getInstance() {
return single;
}
}
2.懶漢式單例類
//懶漢式單例類.在第一次調(diào)用的時(shí)候?qū)嵗?/p>
public class Singleton2 {
//私有的默認(rèn)構(gòu)造子
private Singleton2() {}
//注意,這里沒有final
private static Singleton2 single=null;
//靜態(tài)工廠方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
//對懶漢式單例的改進(jìn)(錯(cuò)誤的改進(jìn))
//實(shí)際上,只有在第一次創(chuàng)建對象的時(shí)候需要加鎖,之后就不需要了 ,這樣可以提升性能
public synchronized static Singleton2 getInstance() {
if (instance == null) {
synchronized(instance){ //鎖住當(dāng)前實(shí)例對象
if(instance == null){
instance = new Singleton2();
}
}
}
return instance;
}
錯(cuò)誤原因:
aA、B線程同時(shí)進(jìn)入了第一個(gè)if判斷
bA首先進(jìn)入synchronized塊,由于instance為null,所以它執(zhí)行instance = new Singleton();
c由于JVM內(nèi)部的優(yōu)化機(jī)制,JVM先畫出了一些分配給Singleton實(shí)例的空白內(nèi)存,并賦值給instance成員(注意此時(shí)JVM沒有開始初始化這個(gè)實(shí)例),然后A離開了synchronized塊。
dB進(jìn)入synchronized塊,由于instance此時(shí)不是null,因此它馬上離開了synchronized塊并將結(jié)果返回給調(diào)用該方法的程序。
e此時(shí)B線程打算使用Singleton實(shí)例,卻發(fā)現(xiàn)它沒有被初始化,于是錯(cuò)誤發(fā)生了。
正確改進(jìn)(使用內(nèi)部類):
JVM內(nèi)部的機(jī)制能夠保證當(dāng)一個(gè)類被加載的時(shí)候,這個(gè)類的加載過程是線程互斥的,JVM能夠幫我們保證instance只被創(chuàng)建一次,
并且會保證把賦值給instance的內(nèi)存初始化完畢,這樣我們就不用擔(dān)心上面的問題。
同時(shí)該方法也只會在第一次調(diào)用的時(shí)候使用互斥機(jī)制,這樣就解決了低性能問題
public?class?Singleton?{??
??
/*?私有構(gòu)造方法,防止被實(shí)例化?*/??
private?Singleton(){
}
/*?此處使用一個(gè)內(nèi)部類來維護(hù)單例?*/??
private?static?class?SingletonFactory?{??
private?static?Singleton?instance?=?new?Singleton();??
}
/*?獲取實(shí)例?*/??
public?static?Singleton?getInstance()?{??
return?SingletonFactory.instance;??
}
/*?如果該對象被用于序列化,可以保證對象在序列化前后保持一致?*/??
public?Object?readResolve()?{??
return?getInstance();??
}
}
其實(shí)說它完美,也不一定,如果在構(gòu)造函數(shù)中拋出異常,實(shí)例將永遠(yuǎn)得不到創(chuàng)建,也會出錯(cuò)????
第二種改進(jìn):
因?yàn)槲覀冎恍枰趧?chuàng)建類的時(shí)候進(jìn)行同步,所以只要將創(chuàng)建和getInstance()分開,
單獨(dú)為創(chuàng)建加synchronized關(guān)鍵字,也是可以的
public class Singleton {
private static Singleton instance=null;
private Singleton(){}
private static synchronized void Init(){
if(instance==null)
instance=new Singletion();
}
public static Singleton getInstance(){
if(instance==null){
Init();
}
return instance;
}
}
3.登記式單例類
import java.util.HashMap;
import java.util.Map;
//登記式單例類.
//類似Spring里面的方法,將類名注冊,下次從里面直接獲取。
public class Singleton3 {
private static MapString,Singleton3 map = new HashMapString,Singleton3();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保護(hù)的默認(rèn)構(gòu)造子
protected Singleton3(){}
//靜態(tài)工廠方法,返還此類惟一的實(shí)例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"---name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
//一個(gè)示意性的商業(yè)方法
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}