設(shè)計(jì)模式的基本概念與區(qū)別

1、設(shè)計(jì)模式有哪些盹憎?

23種設(shè)計(jì)模式
總體分為三大類
創(chuàng)建型設(shè)計(jì)模式筛峭,共5種
簡單工廠、工廠方法模式陪每,抽象工廠模式影晓,單例模式,建造者模式檩禾,原型模式

結(jié)構(gòu)型模式挂签,共7種
適配器模式,裝飾器模式盼产、代理模式饵婆、外觀模式、橋接模式戏售、組合模式侨核、享元模式

行為型模式,共11種
策略模式灌灾,模板方法搓译,觀察者模式,迭代模式锋喜,責(zé)任鏈模式些己,命令模式,備忘錄模式跑芳,狀態(tài)模式轴总,訪問者模式,中介者模式博个,解釋器模式

2、設(shè)計(jì)模式定義

1功偿、 設(shè)計(jì)模式按照類型劃分

  • 創(chuàng)建型設(shè)計(jì)模式:用來解耦對象的實(shí)例化過程盆佣。
  • 結(jié)構(gòu)型設(shè)計(jì)模式:將類和對象按照一定規(guī)則組合成一個(gè)更加強(qiáng)大的結(jié)構(gòu)體。
  • 行為型設(shè)計(jì)模式:定義類和對象的交互行為械荷。

2共耍、 設(shè)計(jì)模式簡單定義


23種設(shè)計(jì)模式簡單定義

3、文字版
1)創(chuàng)建型設(shè)計(jì)模式

  • 單例模式:確保一個(gè)類只有一個(gè)實(shí)例吨瞎,提供一個(gè)全局訪問點(diǎn)
  • 建造者模式:封裝一個(gè)復(fù)雜對象過程痹兜,按照步驟構(gòu)建對象
  • 原型模式:通過復(fù)制現(xiàn)有實(shí)例創(chuàng)建新實(shí)例
  • 簡單工廠模式:一個(gè)工廠類根據(jù)傳入?yún)?shù)決定創(chuàng)建哪一種產(chǎn)品實(shí)例
  • 工廠方法模式:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化那個(gè)類
  • 抽象工廠模式:創(chuàng)建相關(guān)依賴對象家族颤诀,而無須指定具體類

2)結(jié)構(gòu)型設(shè)計(jì)模式

  • 適配器模式:將一個(gè)類的方法或者接口轉(zhuǎn)換成客戶希望另一個(gè)接口
  • 組合模式:將對象組成成樹形結(jié)構(gòu)以表示“整體-部分”的層次結(jié)構(gòu)
  • 裝飾模式:動態(tài)的給對象添加新的功能
  • 外觀模式:對外提供一個(gè)統(tǒng)一方法字旭,用來訪問子系統(tǒng)中一群接口
  • 橋接模式:將抽象部分與實(shí)現(xiàn)部分分離对湃,使他們都可以獨(dú)立進(jìn)行變化
  • 享元模式:通過共享技術(shù)來有效支持大量細(xì)粒度的對象
  • 代理模式:為其他對象提供一種代理以控制對這個(gè)對象的訪問

3)行為型設(shè)計(jì)模式

  • 模板模式:定義一個(gè)算法結(jié)構(gòu),而將一些步驟延遲到子類實(shí)現(xiàn)
  • 解釋器模式:定義一個(gè)語言遗淳,定義它的文法的一種表示拍柒,并定義一個(gè)解釋器
  • 策略模式:定義一系列算法,把它們封裝起來屈暗,并且使它們可以互相替換
  • 狀態(tài)模式:允許一個(gè)對象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為
  • 觀察者模式:對象間一對多依賴關(guān)系拆讯,一個(gè)對象改變,依賴于它對象得到通知并更新
  • 備忘錄模式:在不破壞封裝前提下养叛,保存對象內(nèi)部狀態(tài)
  • 中介者模式:用一個(gè)中介對象來封裝一系列對象交互
  • 命令模式:將命令請求封裝成一個(gè)對象种呐,可以將不同請求來進(jìn)行參數(shù)化
  • 訪問者模式:在不改變數(shù)據(jù)結(jié)構(gòu)的前提下,增加作用于一組元素對象新功能
  • 責(zé)任鏈模式:將請求的發(fā)送者和接受者解耦弃甥,使得多個(gè)對象都有處理這個(gè)請求的機(jī)會
  • 迭代器模式:一種遍歷訪問容器對象中各個(gè)元素的方法陕贮,不暴露該對象內(nèi)部結(jié)構(gòu)
3、動態(tài)代理和靜態(tài)代理區(qū)別

區(qū)別在于代理類生成時(shí)間不同潘飘,根據(jù)程序運(yùn)行時(shí)代理類是否存在

應(yīng)用場景:retrofit使用動態(tài)代理提升擴(kuò)展性

4肮之、動態(tài)代理寫法

參考 https://github.com/yinlingchaoliu/23-design-pattern.git

公共部分

//接口
public interface ILawsuit {

    //提交申請
    void submit();

    //舉證
    void burden();

    //辯護(hù)
    void defend();

    //訴訟完成
    void finish();

}

public class XiaoMin implements ILawsuit {

    @Override
    public void submit() {
        //小民申請仲裁
        System.out.println( "老板年底拖欠工資,特此申請仲裁卜录!" );
    }

    @Override
    public void burden() {
        //小民提交證據(jù)
        System.out.println( "這是合同書和過去一年的銀行工資流水戈擒!" );
    }

    @Override
    public void defend() {
        //鐵證如山
        System.out.println( "證據(jù)確鑿,不需要再說什么艰毒!" );
    }

    @Override
    public void finish() {
        //結(jié)果
        System.out.println( "訴訟成功筐高,判決老板即日起七天內(nèi)結(jié)算工資!" );
    }

}

靜態(tài)代理

/**
 * 代理類
 */
public class Lawyer implements ILawsuit {

    private ILawsuit mLawsuit;

    public Lawyer(ILawsuit mLawsuit) {
        this.mLawsuit = mLawsuit;
    }

    @Override
    public void submit() {
        mLawsuit.submit();
    }

    @Override
    public void burden() {
        mLawsuit.burden();
    }

    @Override
    public void defend() {
        mLawsuit.defend();
    }

    @Override
    public void finish() {
        mLawsuit.finish();
    }
}

測試類
public class TestMain {

    public static void main(String[] args) {
        ILawsuit xiaomin = new XiaoMin();
        //靜態(tài)代理
        ILawsuit lawyer = new Lawyer( xiaomin );
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

動態(tài)代理 第一種寫法

/**
 *
 * 動態(tài)代理
 *
 */
public class DynamicProxy implements InvocationHandler {

    private Object obj;

    public DynamicProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke( obj,args );
        return result;
    }
}


public class TestMain {

    public static void main(String[] args) {
        ILawsuit xiaomin = new XiaoMin();
        //動態(tài)代理
        DynamicProxy proxy = new DynamicProxy( xiaomin );
        //獲取小民的classLoader
        ClassLoader loader = xiaomin.getClass().getClassLoader();
        //動態(tài)代理一個(gè)代理律師
        ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance( loader, new Class[]{ILawsuit.class}, proxy );
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }

}

動態(tài)代理第二種通用式寫法


public class DynamicProxy {

   //需要特別指定泛型類
    public static <T> T create(Class<T> serivce, final Object newInstance) {
        InvocationHandler proxy = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke( newInstance, args );
            }
        };
        ClassLoader loader = serivce.getClassLoader();
        return (T) Proxy.newProxyInstance( loader, new Class[]{serivce}, proxy );
    }
}

    /**
     * 需要那個(gè)接口 泛型指向那個(gè)
     * T必須為接口類
     * @param newInstance
     * @param <T>
     * @return
     */
    public static <T> T create(final Object newInstance) {

        InvocationHandler proxy = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke( newInstance, args );
            }
        };

        //獲得接口列表
        Class[] ifaces = newInstance.getClass().getInterfaces();
        //獲取實(shí)體類classLoader
        ClassLoader loader = newInstance.getClass().getClassLoader();
        //獲得動態(tài)代理實(shí)例
        return (T) Proxy.newProxyInstance( loader, ifaces, proxy );
    }

    //retrofit寫法
    /**
     * 沒有真正實(shí)體類
     * 可以用invoke方法反射
     * @param service
     * @param <T>
     * @return
     */
    public static <T> T create(Class<T> service) {
        ClassLoader loader = service.getClassLoader();

        InvocationHandler proxy = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //這里填寫回調(diào)丑瞧,沒有newInstance retrofit用法
                return null;
            }
        };
        return (T) Proxy.newProxyInstance( loader, new Class[]{service}, proxy );
    }
}

測試類

    public static void main(String args[]){

        //第一種方式:指定接口
        ILawsuit lawsuit =  DynamicProxy.create( ILawsuit.class, new XiaoMin() );
        lawsuit.submit();
        lawsuit.burden();

        //第二種方式:采用接口轉(zhuǎn)換
        ILawsuit mlawsuit =  DynamicProxy.create(  new XiaoMin() );
        mlawsuit.defend();

        IArgue argue =  DynamicProxy.create(  new XiaoMin() );
        argue.argue();

        //轉(zhuǎn)換時(shí) 必須用接口才行
        ILawsuit judge = (ILawsuit)argue;

        judge.finish();
    }
5柑土、簡單工廠、工廠方法绊汹、抽象工廠稽屏、建造者模式區(qū)別

簡單工廠:一個(gè)工廠方法創(chuàng)建不同類型對象
工廠方法:一個(gè)具體工廠類負(fù)責(zé)創(chuàng)建一個(gè)具體對象類型
抽象工廠:一個(gè)具體工廠類負(fù)責(zé)創(chuàng)建一系列相關(guān)對象
建造者模式:對象的構(gòu)建與表現(xiàn)分離,更注重對象創(chuàng)建過程

6西乖、裝飾模式與代理模式區(qū)別狐榔、與橋接者模式相比

1、裝飾模式以客戶端透明方式擴(kuò)展對象的功能获雕,是繼承關(guān)系替代方案薄腻。
代理模式是給一個(gè)對象提供代理對象,并由代理對象來控制原有對象引用
2届案、裝飾模式應(yīng)該為所裝飾對象增強(qiáng)功能庵楷,代理模式對所代理對象施加控制,但不對對象功能本身增加
3、橋接模式主要為應(yīng)對某個(gè)類多個(gè)變化維度增加場景尽纽,通過橋接把多個(gè)變化隔離開

7咐蚯、外觀模式和中介模式區(qū)別

外觀模式重點(diǎn)對外封裝統(tǒng)一高層接口,便于用戶使用蜓斧。
中介模式避免多個(gè)互相協(xié)作對象直接易用仓蛆。他們之間通過一個(gè)中介對象進(jìn)行,從而得到他們耦合松散挎春,易于應(yīng)對變化

8看疙、策略模式和狀態(tài)模式區(qū)別

類型結(jié)構(gòu)一致,本質(zhì)不同直奋,策略模式重在整個(gè)算法的替換能庆,也就是策略替換,而狀態(tài)模式則是通過狀態(tài)來改變行為

9脚线、適配器模式搁胆、裝飾者模式、外觀模式異同

相同之處邮绿,在用戶類與被調(diào)用類之間加了一個(gè)中間層
不同之處
代理對象表示一個(gè)單一對象
外觀對象表示一個(gè)子系統(tǒng)
適配器和外觀是對現(xiàn)存系統(tǒng)封裝
外觀定義新接口渠旁,簡化接口
適配器則是復(fù)用原有接口,側(cè)重于接口轉(zhuǎn)換

10船逮、重構(gòu)之代碼壞味道

記住壞味道顾腊,在文集《重構(gòu) 改善代碼設(shè)計(jì)》-代碼壞味道中
記住一個(gè)原則:事不過三,三則重構(gòu)
常見壞味道要點(diǎn):
1挖胃、代碼重復(fù)
2杂靶、方法過長
3、類功能過多
4酱鸭、過長參數(shù)列表
5吗垮、冗余類
6、需要過多注釋

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凹髓,一起剝皮案震驚了整個(gè)濱河市烁登,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扁誓,老刑警劉巖防泵,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝗敢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)足删,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門寿谴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人失受,你說我怎么就攤上這事讶泰∮缴” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵痪署,是天一觀的道長码泞。 經(jīng)常有香客問我,道長狼犯,這世上最難降的妖魔是什么余寥? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮悯森,結(jié)果婚禮上宋舷,老公的妹妹穿的比我還像新娘。我一直安慰自己瓢姻,他們只是感情好祝蝠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幻碱,像睡著了一般绎狭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上褥傍,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天儡嘶,我揣著相機(jī)與錄音,去河邊找鬼摔桦。 笑死社付,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的邻耕。 我是一名探鬼主播鸥咖,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兄世!你這毒婦竟也來了啼辣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤御滩,失蹤者是張志新(化名)和其女友劉穎鸥拧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體削解,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡富弦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氛驮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腕柜。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盏缤,到底是詐尸還是另有隱情砰蠢,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布唉铜,位于F島的核電站台舱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏潭流。R本人自食惡果不足惜竞惋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幻枉。 院中可真熱鬧碰声,春花似錦、人聲如沸熬甫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椿肩。三九已至瞻颂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間郑象,已是汗流浹背贡这。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厂榛,地道東北人盖矫。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像击奶,于是被迫代替她去往敵國和親辈双。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355