設(shè)計模式涉獵

gof分類:

創(chuàng)建型模式旁钧,共五種:工廠方法模式吸重、抽象工廠模式、單例模式歪今、建造者模式嚎幸、原型模式。

結(jié)構(gòu)型模式寄猩,共七種:適配器模式嫉晶、裝飾器模式、代理模式、外觀模式替废、橋接模式箍铭、組合模式、享元模式椎镣。

行為型模式坡疼,共十一種:策略模式、模板方法模式衣陶、觀察者模式柄瑰、迭代子模式、責(zé)任鏈模式剪况、命令模式教沾、備忘錄模式、狀態(tài)模式译断、訪問者模式授翻、中介者模式、解釋器模式孙咪。

這里只總結(jié)幾種比較重要的:
———————————————————————————————————————

一堪唐、創(chuàng)建型:

1.簡單工廠模式

簡單工廠模式通常就是這樣,一個工廠類 XxxFactory翎蹈,里面有一個靜態(tài)方法淮菠,根據(jù)我們不同的參數(shù),使用swtich +case 返回不同的派生自同一個父類(同一職責(zé))(或?qū)崿F(xiàn)同一接口)的實(shí)例對象荤堪。

把或者各個類型的都統(tǒng)一放到./工廠產(chǎn)品/目錄下,工廠傳入要匹配的類型, 以匹配類型為文件名合陵。需要實(shí)例化的時候就require該文件,這樣也保證了各個開發(fā)人員的代碼不沖突澄阳。后期也易擴(kuò)展拥知,新增一種類型的用戶,只需新增一個類型的文件即可符合開閉原則碎赢。

2.工廠模式(需要使用兩個或兩個以上的工廠時)

圖片.png

3.抽象工廠模式(通過抽象產(chǎn)品來抽象了工廠)

涉及定義某個產(chǎn)品的一系列附件的集合時, 不再定義組件工廠,直接定義產(chǎn)品工廠,由產(chǎn)品工廠來定義所需組件

4.單例模式

1低剔、單例類只能有一個實(shí)例。
2肮塞、單例類必須自己創(chuàng)建自己的唯一實(shí)例襟齿。
3、單例類必須給所有其他對象提供這一實(shí)例峦嗤。

懶漢式單例(在第一次調(diào)用的時候?qū)嵗约?:
public class Singleton {  
   //不再提供給其他的地方實(shí)例化
    private Singleton() {}  
    private static Singleton single=null;  
    //靜態(tài)工廠方法,Singleton的唯一實(shí)例只能通過getInstance()方法訪問蕊唐。為空的時候才生產(chǎn)
   //如果把實(shí)例寫在成員變量里則法不能把其他不需要實(shí)例的常用方法放入這里,會導(dǎo)致在不需要時創(chuàng)建實(shí)例。
    public static Singleton getInstance() {  
         if (single == null) {    
             single = new Singleton();  
         }    
        return single;  
    }  
}  

懶漢式單例的實(shí)現(xiàn)沒有考慮線程安全問題烁设,它是線程不安全的,并發(fā)環(huán)境下很可能出現(xiàn)多個Singleton實(shí)例,要實(shí)現(xiàn)線程安全装黑,有以下三種方式(只記錄兩種):
1副瀑、在getInstance方法上加同步synchronized
2、靜態(tài)內(nèi)部類(既實(shí)現(xiàn)了線程安全恋谭,又避免了同步帶來的性能影響)

Java機(jī)制規(guī)定糠睡,內(nèi)部類只有在調(diào)用內(nèi)部類方法第一次調(diào)用的時候才會被加載(實(shí)現(xiàn)了延遲加載效果),而且其加載過程是線程安全的(實(shí)現(xiàn)線程安全)疚颊。內(nèi)部類加載的時候?qū)嵗淮蝘nstance狈孔。

另外,外部類加載的時候,內(nèi)部類不會被加載材义,靜態(tài)內(nèi)部類只是調(diào)用的時候用了外部類的名字而已均抽。

public class Singleton {    
    private static class LazyHolder {  //靜態(tài)類懶漢式視為延遲加載的餓漢式  
       private static final Singleton INSTANCE = new Singleton();    
    }    
    private Singleton (){}    
    public static final Singleton getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}    
餓漢式單例(餓漢式單例類.在類初始化時,已經(jīng)自行實(shí)例化,天生是線程安全的):
public class Singleton1 {  
    private Singleton1() {}  
    private static final Singleton1 single = new Singleton1();  
    //靜態(tài)工廠方法   
    public static Singleton1 getInstance() {  
        return single;  
    }  
} 

5.建造者模式 參考

是將一個復(fù)雜的對象的構(gòu)建與它的表示分離其掂,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示油挥。
(例如造汽車與買汽車)
一般包括以下幾個角色:

  1. builder(抽象建造者):給出一個抽象結(jié)論,以規(guī)范產(chǎn)品對象的各個組成成分的建造款熬。這個接口規(guī)定要實(shí)現(xiàn)復(fù)雜對象的那些部分的創(chuàng)建深寥,并不涉及具體的對象部件的創(chuàng)建。
  2. ConcreteBuilder(具體建造者):實(shí)現(xiàn)Builder接口贤牛,針對不同的商業(yè)邏輯惋鹅,具體化復(fù)雜對象的各部分的創(chuàng)建。在構(gòu)造過程完成后殉簸,提供產(chǎn)品的實(shí)例负饲。
  3. Director(指導(dǎo)者):調(diào)用具體建造者來創(chuàng)建復(fù)雜對象的各個部分,在指導(dǎo)者中不涉及具體產(chǎn)品的信息喂链,只負(fù)責(zé)保證對象各部分完整創(chuàng)建或按某種順序創(chuàng)建返十。
  4. Product(產(chǎn)品類):要創(chuàng)建的復(fù)雜對象。
適用場景

需要生產(chǎn)的產(chǎn)品對象有復(fù)雜的內(nèi)部結(jié)構(gòu)椭微。
需要生產(chǎn)的產(chǎn)品對象的屬性相互依賴洞坑,建造者模式可以強(qiáng)迫生成順序。
在對象創(chuàng)建過程中會使用到系統(tǒng)中的一些其它對象蝇率,這些對象在產(chǎn)品對象的創(chuàng)建過程中不易得到迟杂。

———————————————————————————————————————

二、結(jié)構(gòu)型

1.適配器模式

適配器就是一種適配中間件本慕,它存在于不匹配的二者之間排拷,用于連接二者,將不匹配變得匹配锅尘,簡單點(diǎn)理解就是平常所見的轉(zhuǎn)接頭监氢,轉(zhuǎn)換器之類的存在布蔗。

適配器模式有兩種:類適配器、對象適配器浪腐、接口適配器
前二者在實(shí)現(xiàn)上有些許區(qū)別纵揍,作用一樣,第三個接口適配器差別較大议街。

類適配器模式:

當(dāng)我們要訪問的接口A中沒有我們想要的方法 泽谨,卻在另一個接口B中發(fā)現(xiàn)了合適的方法,我們又不能改變訪問接口A特漩,在這種情況下吧雹,我們可以定義一個適配器p來進(jìn)行中轉(zhuǎn),這個適配器p要實(shí)現(xiàn)我們訪問的接口A涂身,這樣我們就能繼續(xù)訪問當(dāng)前接口A中的方法(雖然它目前不是我們的菜)雄卷,然后再繼承接口B的實(shí)現(xiàn)類BB,這樣就完成了一個簡單的類適配器访得。

1 public class Adapter extends Usber implements Ps2 {
2 //在實(shí)現(xiàn)自己接口A的同時繼承要額外訪問的接口B的實(shí)現(xiàn);類Usber
3     @Override
4     public void isPs2() {
5         isUsb();
6     }
7 
8 }
對象適配器模式 :

我們可以定義一個適配器p來進(jìn)行中轉(zhuǎn)龙亲,這個適配器p要實(shí)現(xiàn)我們訪問的接口A,這樣我們就能繼續(xù)訪問當(dāng)前接口A中的方法(雖然它目前不是我們的菜)悍抑,然后在適配器P中定義私有變量C(對象)(B接口指向變量名)鳄炉,再定義一個帶參數(shù)的構(gòu)造器用來為對象C賦值,再在A接口的方法實(shí)現(xiàn)中使用對象C調(diào)用其來源于B接口的方法搜骡。

 1 public class Adapter implements Ps2 {
 2     //
 3     private Usb usb;
 4     public Adapter(Usb usb){
 5         this.usb = usb;
 6     }
 7     @Override
 8     public void isPs2() {
 9         usb.isUsb();
10     }
11 
12 }
接口適配器模式 :

當(dāng)存在這樣一個接口拂盯,其中定義了N多的方法,而我們現(xiàn)在卻只想使用其中的一個到幾個方法记靡,如果我們直接實(shí)現(xiàn)接口谈竿,那么我們要對所有的方法進(jìn)行實(shí)現(xiàn),哪怕我們僅僅是對不需要的方法進(jìn)行置空(只寫一對大括號摸吠,不做具體方法實(shí)現(xiàn))也會導(dǎo)致這個類變得臃腫空凸,調(diào)用也不方便,這時我們可以使用一個抽象類作為中間件寸痢,即適配器呀洲,用這個抽象類實(shí)現(xiàn)接口,而在抽象類中所有的方法都進(jìn)行置空啼止,那么我們在創(chuàng)建抽象類的繼承類道逗,而且重寫我們需要使用的那幾個方法即可。

使用場景:

(1)類:想要使用一個已經(jīng)存在的類献烦,但是它卻不符合現(xiàn)有的接口規(guī)范滓窍,導(dǎo)致無法直接去訪問,這時創(chuàng)建一個適配器就能間接去訪問這個類中的方法巩那。
(2)對象:我們有一個類吏夯,想將其設(shè)計為可重用的類(可被多處訪問)此蜈,我們可以創(chuàng)建適配器來將這個類來適配其他沒有提供合適接口的類。
(2)接口:想要使用接口中的某個或某些方法锦亦,但是接口中有太多方法舶替,我們要使用時必須實(shí)現(xiàn)接口并實(shí)現(xiàn)其中的所有方法令境,可以使用抽象類來實(shí)現(xiàn)接口杠园,并不對方法進(jìn)行實(shí)現(xiàn)(僅置空),然后我們再繼承這個抽象類來通過重寫想用的方法的方式來實(shí)現(xiàn)舔庶。這個抽象類就是適配器抛蚁。

2.代理模式

代理模式給某一個對象提供一個代理對象,并由代理對象控制對原對象的引用
在某些情況下惕橙,一個客戶類不想或者不能直接引用一個委托對象瞧甩,而代理類對象可以在客戶類和委托對象之間起到中介的作用,其特征是代理類和委托類實(shí)現(xiàn)相同的接口弥鹦。

包含以下角色:

ISubject:抽象接口肚逸。該接口是 真實(shí)對象 和它的 代理 共用的接口。

RealSubject:真實(shí)主題角色彬坏,是實(shí)現(xiàn)抽象主題接口的類朦促。

Proxy:代理角色,內(nèi)部含有對真實(shí)對象RealSubject的引用栓始,從而可以操作真實(shí)對象务冕。代理對象提供與真實(shí)對象相同的接口,以便在任何時刻都能代替真實(shí)對象幻赚。同時禀忆,代理對象可以在執(zhí)行真實(shí)對象操作時,附加其他的操作落恼,相當(dāng)于對真實(shí)對象進(jìn)行封裝箩退。

靜態(tài)代理

優(yōu)點(diǎn):可以做到在符合開閉原則的情況下對目標(biāo)對象進(jìn)行功能擴(kuò)展。
缺點(diǎn):我們得為每一個服務(wù)都得創(chuàng)建代理類佳谦,工作量太大戴涝,不易管理。同時接口一旦發(fā)生改變吠昭,代理類也得相應(yīng)修改喊括。

//以買房的中介過程為例
//Proxy:代理角色
 package main.java.proxy.impl;
 
 import main.java.proxy.BuyHouse;//中介服務(wù)接口
 
 public class BuyHouseProxy implements BuyHouse {
 
     private BuyHouse buyHouse;
 
     public BuyHouseProxy(final BuyHouse buyHouse) { //主體(服務(wù))角色買房實(shí)現(xiàn)(需求)傳入
         this.buyHouse = buyHouse;
     }
 
     @Override
     public void buyHosue() { //中介自己的買房實(shí)現(xiàn)
         System.out.println("買房前準(zhǔn)備");
         buyHouse.buyHosue();
         System.out.println("買房后裝修");
 
     }
 }

———————————————————————————————————————

三、行為型

1.觀察者模式

在對象之間定義了一對多的依賴矢棚,這樣一來郑什,當(dāng)一個對象改變狀態(tài),依賴它的對象(觀察者)會收到通知并自動更新
其實(shí)就是發(fā)布訂閱模式蒲肋,發(fā)布者發(fā)布信息蘑拯,訂閱者獲取信息钝满,訂閱了就能收到信息,沒訂閱就收不到信息申窘。

結(jié)構(gòu)圖:
圖片.png

上圖有以下角色:

抽象被觀察者角色:也就是一個抽象主題弯蚜,它把所有對觀察者對象的引用保存在一個集合中,每個主題都可以有任意數(shù)量的觀察者剃法。抽象主題提供一個接口碎捺,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實(shí)現(xiàn)贷洲。

聲明了添加收厨、刪除、通知觀察者方法
public interface Observerable {
    
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
    
}

抽象觀察者角色:為所有的具體觀察者定義一個接口优构,在得到主題通知時更新自己诵叁。

定義了一個update()方法,當(dāng)被觀察者調(diào)用notifyObservers()方法時钦椭,觀察者的update()方法會被回調(diào)拧额。
public interface Observer {
    public void update(String message);
}

具體被觀察者角色:也就是一個具體的主題,在集體主題的內(nèi)部狀態(tài)改變時彪腔,所有登記過的觀察者發(fā)出通知侥锦。

對Observerable接口的三個方法進(jìn)行了具體實(shí)現(xiàn),同時有一個List集合漫仆,用以保存注冊的觀察者捎拯,等需要通知觀察者時,遍歷該集合即可盲厌。
   //注意到這個List集合的泛型參數(shù)為Observer接口署照,設(shè)計原則:面向接口編程而不是面向?qū)崿F(xiàn)編程
    private List<Observer> list;
    private String message;
    
    public WechatServer() { //使用微信公眾號訂閱的例子
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //遍歷
    @Override
    public void notifyObserver() { //對所有用戶進(jìn)行狀態(tài)更改, 這里是消息數(shù)+1
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服務(wù)更新消息: " + s);
        //消息更新,通知所有觀察者
        notifyObserver();
    }

具體觀察者角色:實(shí)現(xiàn)抽象觀察者角色所需要的更新接口吗浩,一邊使本身的狀態(tài)與制圖的狀態(tài)相協(xié)調(diào)建芙。

實(shí)現(xiàn)更新方法供被觀察者調(diào)用
public class User implements Observer {

    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        this.message = message;
        read();
    }
    
    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市懂扼,隨后出現(xiàn)的幾起案子禁荸,更是在濱河造成了極大的恐慌,老刑警劉巖阀湿,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赶熟,死亡現(xiàn)場離奇詭異,居然都是意外死亡陷嘴,警方通過查閱死者的電腦和手機(jī)映砖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灾挨,“玉大人邑退,你說我怎么就攤上這事竹宋。” “怎么了地技?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵蜈七,是天一觀的道長。 經(jīng)常有香客問我莫矗,道長飒硅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任趣苏,我火速辦了婚禮狡相,結(jié)果婚禮上梯轻,老公的妹妹穿的比我還像新娘食磕。我一直安慰自己,他們只是感情好喳挑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布彬伦。 她就那樣靜靜地躺著,像睡著了一般伊诵。 火紅的嫁衣襯著肌膚如雪单绑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天曹宴,我揣著相機(jī)與錄音搂橙,去河邊找鬼。 笑死笛坦,一個胖子當(dāng)著我的面吹牛区转,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播版扩,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼废离,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了礁芦?” 一聲冷哼從身側(cè)響起蜻韭,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柿扣,沒想到半個月后肖方,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡未状,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年俯画,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娩践。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡活翩,死狀恐怖烹骨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情材泄,我是刑警寧澤沮焕,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站拉宗,受9級特大地震影響峦树,放射性物質(zhì)發(fā)生泄漏册踩。R本人自食惡果不足惜犹赖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望帽借。 院中可真熱鬧姐浮,春花似錦谷遂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛋逾,卻和暖如春集晚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背区匣。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工偷拔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亏钩。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓莲绰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親铸屉。 傳聞我的和親對象是個殘疾皇子钉蒲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 創(chuàng)建型模式 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計模式之一。這種類型的設(shè)...
    liuyang7519閱讀 327評論 0 2
  • 創(chuàng)建型模式 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計模式之一彻坛。這種類型的設(shè)...
    隔墻送來秋千影閱讀 2,670評論 0 11
  • 一顷啼、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式昌屉、抽象工廠模式钙蒙、單例模式、建造者...
    RamboLI閱讀 751評論 0 1
  • 一扛施、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式鸿捧,共五種:工廠方法模式、抽象工廠模式疙渣、單例模式匙奴、建造者...
    AI喬治閱讀 1,558評論 0 2
  • 0.提前說明 模式選擇的方法1)模式的功能——看是否能解決問題2)模式的本質(zhì)——看模式是否主要用來解決這類問題3)...
    王偵閱讀 1,054評論 0 1