筆者能力有限,總結(jié)有誤的地方,請(qǐng)讀者協(xié)作更正。需要了解更多,請(qǐng)閱讀相關(guān)書籍。
能說出來解釋清楚,最好能寫出偽代碼
23種設(shè)計(jì)模式分3類:創(chuàng)建型5種,結(jié)構(gòu)型分7種,行為型11種
設(shè)計(jì)模式的6大原則:
1.單例模式8種
基本實(shí)現(xiàn)思路:保證JVM中只能創(chuàng)建一個(gè)該對(duì)象的實(shí)例。對(duì)頻繁創(chuàng)建和銷毀對(duì)象時(shí)使用;工具類使用;
實(shí)現(xiàn)步驟:
?私有靜態(tài)變量;私有構(gòu)造方法;
?靜態(tài)方法,調(diào)用該方法,持有對(duì)象引用,返回該引用;引用為空,創(chuàng)建實(shí)例。
1)餓漢模式(靜態(tài)常量)可用
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
優(yōu)點(diǎn):避免線程同步
缺點(diǎn):類加載之后,對(duì)象就創(chuàng)建出來在哪里放著,不管用不用,沒有懶加載效果,內(nèi)存浪費(fèi)。
2)餓漢式(靜態(tài)代碼塊)可用
把對(duì)象的創(chuàng)建放在靜態(tài)代碼塊中,優(yōu)缺點(diǎn)和上面一樣。
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
3)懶漢模式(線程不安全)不可用
把對(duì)象的創(chuàng)建放在方法中,需要用的時(shí)候在創(chuàng)建;能實(shí)現(xiàn)懶加載,存在線程不安全。
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
4)懶漢模式(線程安全,同步方法)可用,不推薦
加鎖,懶加載,線程安全,但是效率低
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
5)懶漢模式(線程安全,同步代碼塊)不可用
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
線程安全,但是會(huì)產(chǎn)生多個(gè)實(shí)例;
6)雙重檢查(推薦用)
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
} } }
return singleton;
}
}
進(jìn)行了兩次if (singleton == null)檢查,這樣就可以保證線程安全了。這樣,實(shí)例化代碼只用執(zhí)行一次,后面再次訪問時(shí),判斷if (singleton == null),直接return實(shí)例化對(duì)象。
優(yōu)點(diǎn):線程安全;延遲加載;效率較高。
7)靜態(tài)內(nèi)部類(推薦用)
public class Singleton
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
類的靜態(tài)屬性只會(huì)在第一次加載類的時(shí)候進(jìn)行初始化,JVM能夠幫我們保證線程安全,在進(jìn)行初始化的時(shí)候,別的線程無法進(jìn)入。
優(yōu)點(diǎn):線程安全,延遲加載,效率高。
8)枚舉(推薦用)
public enum Singleton{
Instance;
private void EvenMethod(){
}
}
JDK1.5中添加的枚舉來實(shí)現(xiàn)單例模式。
不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對(duì)象。
2.工廠方法
簡單工廠方法
不同的類實(shí)現(xiàn)同一個(gè)接口,創(chuàng)建一個(gè)簡單工廠來為這些類創(chuàng)建實(shí)例;
例如:發(fā)送短信,發(fā)送郵件,將發(fā)送抽取出來作為接口,建一個(gè)簡單工廠來實(shí)現(xiàn)發(fā)送的實(shí)例,當(dāng)然還有其它的寫法。
工廠方法
簡單工廠存在的問題,類的創(chuàng)建依賴于工廠類,想要修改程序就需要修改工廠,違背了閉包原則
工廠方法,擴(kuò)展功能,直接增加工廠類。
3.抽象工廠
工廠方法中,一個(gè)工廠只能生產(chǎn)一種產(chǎn)品。重點(diǎn)在于產(chǎn)品,如果一個(gè)方法需要有大量的實(shí)現(xiàn)細(xì)節(jié),很多代碼需要圍繞這個(gè)產(chǎn)品展開,推薦使用工廠方法。
抽象工廠中,一個(gè)工廠可以創(chuàng)建多種產(chǎn)品類,因?yàn)槌橄蠊S中有一堆的工廠方法,一個(gè)工廠方法返回對(duì)應(yīng)的數(shù)據(jù)類型。重點(diǎn)在于數(shù)量,如果要求不同的產(chǎn)品線,保持接口一致,推薦使用抽象工廠方法。
4.代理模式
1)就是用另外一個(gè)類代替目標(biāo)類的操作,同時(shí)能夠提供額外的操作;
比如:房地產(chǎn)中介,客戶,和房東就是一個(gè)代理模式;
2)分類:靜態(tài)代理,和動(dòng)態(tài)代理 spring中AOP應(yīng)用了兩種代理模式,ciglib動(dòng)態(tài)代理,jdk動(dòng)態(tài)代理 詳解Spring的AOP?
1.1 靜態(tài)代理
特點(diǎn):實(shí)現(xiàn)和被代理這相同的接口,能夠執(zhí)行代理者相同的方法,添加額外的功能操作
缺點(diǎn):一個(gè)目標(biāo)對(duì)象就需要一個(gè)代理類,一個(gè)明星就需要一個(gè)經(jīng)濟(jì)人
復(fù)用性不高,不通用
1.2 動(dòng)態(tài)代理
分為-->JDK代理 CGlib代理 -jdk動(dòng)態(tài)代理
特點(diǎn):實(shí)現(xiàn)相同的接口,執(zhí)行目標(biāo)對(duì)象的方法,能做額外的操作,
優(yōu)點(diǎn):一個(gè)代理類,能為很多目標(biāo)類服務(wù),解耦,高復(fù)用
缺點(diǎn):只能處理事務(wù),不具備通用性(日志,安全,權(quán)限等)
-CGlib動(dòng)態(tài)代理
特點(diǎn):執(zhí)行目標(biāo)對(duì)象的方法,能做額外的操作
優(yōu)點(diǎn):一個(gè)代理類,能為很多目標(biāo)類服務(wù),解耦,高復(fù)用,而且不需要實(shí)現(xiàn)接口,
1.3 Spring 生成代理對(duì)象
Spring整合了JDK代理和Cglib代理,
Jdk代理實(shí)現(xiàn)的是invocationHandler接口;Cglib實(shí)現(xiàn)的是MethodInterceptor接口
實(shí)現(xiàn)著兩個(gè)接口,spring代理模式內(nèi)部能夠的自由切換。讓代理模式復(fù)用性更高,使用更方便。
5.裝飾器模式
裝飾模式和代理模式很像,都是為了擴(kuò)展功能,
裝飾模式要求給一個(gè)對(duì)象動(dòng)態(tài)的增加一些新的功能,要求裝飾對(duì)象和被裝飾對(duì)象實(shí)現(xiàn)共同的接口,裝飾對(duì)象持有被裝飾對(duì)象的引用。
6.策略模式
就是定義一系列的算法族,將每一個(gè)算法封裝成獨(dú)立的類,然后所有的類實(shí)現(xiàn)統(tǒng)一的接口,這些算法之間可以相互替換,每一個(gè)算法的變化不會(huì)影響到用戶的使用。
需要設(shè)計(jì)一個(gè)接口,為一序列類提供統(tǒng)一的方法,多個(gè)實(shí)現(xiàn)類實(shí)現(xiàn)該接口,設(shè)計(jì)一個(gè)抽象類,提供輔助函數(shù)。
7.觀察者模式
是一種一隊(duì)多的關(guān)系,就像公眾號(hào)和粉絲的關(guān)系;
當(dāng)一個(gè)對(duì)象發(fā)生變化時(shí)候,其它依賴于該對(duì)象的類都會(huì)收到通知;
8.責(zé)任鏈模式
就是,有多個(gè)對(duì)象,每一個(gè)對(duì)象持有下一個(gè)對(duì)象的引用,形成一條鏈,請(qǐng)求在這條鏈上傳遞,直到被某一對(duì)象被處理,但是請(qǐng)求并不知道是哪一個(gè)對(duì)象處理了這個(gè)請(qǐng)求。
比喻:我去拜訪元首,第一道安檢,讓我初始通行證;第二道安全,搜身;第三道安檢,是否預(yù)約;每一次安檢負(fù)責(zé)每一次安檢的工作,所有的安檢形成一條鏈,我作為一個(gè)對(duì)象在這條鏈上傳遞,安檢不通過,拋異常。
更多建議: