設(shè)計(jì)模式之創(chuàng)建型模式總結(jié) - Creational Patterns

前言

以前學(xué)習(xí)設(shè)計(jì)模式的時(shí)候, 通常都是咖啡館, 披薩店, 各種各樣的紅綠頭鴨. 明顯地, 這些概念需要更新一下, 這次我們用MacBook和XPS13兩臺(tái)電腦作為例子來(lái)快速?gòu)?fù)習(xí)創(chuàng)建型設(shè)計(jì)模式.

創(chuàng)建型模型簡(jiǎn)單直接, 所以大部分模式直接通過(guò)UML進(jìn)行展示, 個(gè)別需要特別注意的將會(huì)以代碼的形式展示.

完整代碼已上傳至GitOSC

簡(jiǎn)單工廠

簡(jiǎn)單工廠可以為客戶端選擇具體的實(shí)現(xiàn)

下面是LaptopFactory生產(chǎn)MacBook和Xps13的例子

UML

簡(jiǎn)單工廠模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        // 生成rmbp
        final MacBook implA = LaptopFactory.createMacBook();
        implA.doSomething();
        // 生產(chǎn)xps
        final Xps13 implB = LaptopFactory.createXps13();
        implB.doSomething();
    }
}

工廠方法模式 - Factory method

與簡(jiǎn)單工廠的區(qū)別在于工廠方法模式允許將類的實(shí)例化推遲到子類中, 如果把工廠方法中的具體實(shí)現(xiàn)放到父類中, 那么就等同于簡(jiǎn)單工廠

下面是LaptopFactory將生產(chǎn)Laptop的功能分別推遲至AppleFactoryDellFactory的例子

UML

工廠方法模式

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final LaptopFactory laptopFactory = new AppleFactory();
        laptopFactory.someWork();
    }
}

小結(jié)

工廠父類是一個(gè)抽象類, 里面有個(gè)protected abstract方法就是工廠方法

一般工廠方法返回的是被創(chuàng)建對(duì)象的接口對(duì)象, 當(dāng)然也可以是抽象類或者一個(gè)具體的類的實(shí)例

工廠方法可以看成一個(gè)生成對(duì)象的抽象方法

抽象工廠模式 - Abstract factory

創(chuàng)建一系列的產(chǎn)品對(duì)象, 而且這一系列對(duì)象是構(gòu)建新的對(duì)象所需要的組成部分, 簡(jiǎn)而言之就是這一系列被創(chuàng)建的對(duì)象相互之間是有約束的.

如今不僅需要生產(chǎn)電腦, 還要生產(chǎn)電源適配器, 這兩個(gè)組成了產(chǎn)品簇. 顯而易見的是XPS不能使用MacBook的電源.

UML

抽象工廠模式

Client Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final LaptopFactory factory = new AppleFactory();
        factory.createLaptop();
        factory.createPowerAdaptor();
    }
}

原型模式 - Prototype

<u>可忽略</u>, 在實(shí)際工作中更多地會(huì)使用第三方類庫(kù)完成深拷貝

下面是克隆MacBook的例子

UML

原型模式

Usage

/**
 * @author Zhao Junjian
 */
public class PrototypeTester {
    @Test
    public void testClone() throws Exception {
        // 你就只管我們生成一個(gè)List對(duì)象就行
        final List<MacBook.Cpu> cpuList = new ArrayList<>();
        for (int i = 1; i <= 4; i++) {
            final MacBook.Cpu cpu = new MacBook.Cpu(i);
            cpuList.add(cpu);
        }
        final MacBook macBook = new MacBook();
        macBook.setCpuArray(cpuList.toArray(new MacBook.Cpu[cpuList.size()]));
        macBook.setCpuList(cpuList);
        macBook.setKeyboard(87);
        macBook.setMemory("16G");
        // 全部準(zhǔn)備完成, 我們就開始克隆一個(gè)新的實(shí)體
        final MacBook newMacBook = macBook.clone();
        Assert.assertEquals(macBook, newMacBook);
        // 修改引用類型
        final MacBook.Cpu newCpu = new MacBook.Cpu(5);
        cpuList.add(newCpu);
        newMacBook.setCpuList(cpuList);
        // 如果這里拋出異常, 就證明是淺拷貝. 實(shí)際情況就是淺拷貝.
        Assert.assertNotEquals(macBook, newMacBook);
    }
}

小結(jié)

MacBook需要實(shí)現(xiàn)標(biāo)識(shí)接口Cloneable, 并在clone()方法里面顯式地調(diào)用父類的clone()

@Override
protected MacBook clone() throws CloneNotSupportedException {
  return (MacBook) super.clone();
}

單例模式 - Singleton

這里著重于講解懶漢式, 因?yàn)橛行枰⒁獾募?xì)節(jié), 所以直接貼代碼.

實(shí)現(xiàn)單例有3種模式, 嵌套類, 雙重檢查和枚舉

嵌套類 holder
/**
 * @author Zhao Junjian
 */
public class DellFactory {

    private DellFactory() {
        System.out.println("dell is the best");
    }

    private static final class DellFactoryHolder {
        private static final DellFactory FACTORY = new DellFactory();
    }

    public static DellFactory getInstance() {
        return DellFactoryHolder.FACTORY;
    }

}
雙重檢查 double-checked
/**
 * @author Zhao Junjian
 */
public class AppleFactory {
    private static volatile AppleFactory FACTORY;

    public static AppleFactory getInstance() {
        if (FACTORY == null) {
            //Client.LATCH.await();
            synchronized (AppleFactory.class) {
                if (FACTORY == null) {
                    FACTORY = new AppleFactory();
                }
            }
        }
        return FACTORY;
    }

    private AppleFactory() {
        System.out.println(Thread.currentThread().getName() + " wanna get a hurt");
    }

}
枚舉 enum
/**
 * @author Zhao Junjian
 */
public enum RazerFactory {
    STEALTH;

    public void doSomething() {
        // ...
    }
}

建造者模式/生成器模式 - Builder

實(shí)際中有兩種方法可以快速構(gòu)建Fluent API, 第一是安裝插件, 第二是使用Lombok

被構(gòu)建者的私有構(gòu)造器, 公開靜態(tài)的builder()方法

下面是通過(guò)建造者生成MacBook的例子

/**
 * @author Zhao Junjian
 */
@Data
public class MacBook {
    private String processor;

    private int memory;

    private long capacity;

    private String keyboard;

    private MacBook(Builder builder) {
        processor = builder.processor;
        memory = builder.memory;
        capacity = builder.capacity;
        keyboard = builder.keyboard;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {
        private String processor;
        private int memory;
        private long capacity;
        private String keyboard;

        public Builder processor(String val) {
            processor = val;
            return this;
        }

        public Builder memory(int val) {
            memory = val;
            return this;
        }

        public Builder capacity(long val) {
            capacity = val;
            return this;
        }

        public Builder keyboard(String val) {
            keyboard = val;
            return this;
        }

        public MacBook build() {
            return new MacBook(this);
        }
    }
}

Usage

/**
 * @author Zhao Junjian
 */
public class Client {
    public static void main(String[] args) {
        final MacBook macBook = MacBook.builder().processor("core").memory(9481).capacity(102931L).build();
    }
}

作者:Chris
原博客:http://blog.chriscs.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市三妈,隨后出現(xiàn)的幾起案子塞赂,更是在濱河造成了極大的恐慌乖酬,老刑警劉巖脊岳,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異愚臀,居然都是意外死亡科雳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門蕾域,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拷肌,“玉大人,你說(shuō)我怎么就攤上這事旨巷【拊担” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵采呐,是天一觀的道長(zhǎng)若锁。 經(jīng)常有香客問(wèn)我,道長(zhǎng)斧吐,這世上最難降的妖魔是什么又固? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任仲器,我火速辦了婚禮,結(jié)果婚禮上仰冠,老公的妹妹穿的比我還像新娘乏冀。我一直安慰自己,他們只是感情好洋只,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布辆沦。 她就那樣靜靜地躺著,像睡著了一般识虚。 火紅的嫁衣襯著肌膚如雪肢扯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天担锤,我揣著相機(jī)與錄音蔚晨,去河邊找鬼。 笑死妻献,一個(gè)胖子當(dāng)著我的面吹牛蛛株,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播育拨,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼谨履,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了熬丧?” 一聲冷哼從身側(cè)響起笋粟,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎析蝴,沒(méi)想到半個(gè)月后害捕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闷畸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年尝盼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佑菩。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盾沫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殿漠,到底是詐尸還是另有隱情赴精,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布绞幌,位于F島的核電站蕾哟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谭确,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一帘营、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧琼富,春花似錦仪吧、人聲如沸庄新。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)择诈。三九已至械蹋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間羞芍,已是汗流浹背哗戈。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荷科,地道東北人唯咬。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像畏浆,于是被迫代替她去往敵國(guó)和親胆胰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • 1 場(chǎng)景問(wèn)題# 1.1 選擇組裝電腦的配件## 舉個(gè)生活中常見的例子——組裝電腦刻获,我們?cè)诮M裝電腦的時(shí)候蜀涨,通常需要選...
    七寸知架構(gòu)閱讀 4,283評(píng)論 6 66
  • 1 場(chǎng)景問(wèn)題# 1.1 導(dǎo)出數(shù)據(jù)的應(yīng)用框架## 考慮這樣一個(gè)實(shí)際應(yīng)用:實(shí)現(xiàn)一個(gè)導(dǎo)出數(shù)據(jù)的應(yīng)用框架,來(lái)讓客戶選擇數(shù)據(jù)...
    七寸知架構(gòu)閱讀 6,533評(píng)論 6 72
  • 設(shè)計(jì)模式匯總 一蝎毡、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用厚柳、多...
    MinoyJet閱讀 3,906評(píng)論 1 15
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法沐兵,內(nèi)部類的語(yǔ)法别垮,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法扎谎,線程的語(yǔ)...
    子非魚_t_閱讀 31,587評(píng)論 18 399
  • 所謂奔波 大概就是外衣上沾滿風(fēng)塵 內(nèi)衣里吸滿汗水 看遍萬(wàn)種光景 依然不能平靜
    cookie貓閱讀 534評(píng)論 0 0