23種設計模式(三)-對象創建

  • Factory Method 工廠方法

模式定義:
定義一個用于創建對象的接口,讓子類決定實例化哪一個類。Factory Method使得一個類的實例化延遲(目的:解耦,手段:虛函數)到子類。

組件:
抽象工廠(AbstractFactory):提供了創建產品的接口,調用者通過它訪問具體工廠的工廠方法 newProduct() 來創建產品。
具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的創建。
抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能。
具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間一一對應。

類圖.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/16-21:36
 */
public class FactoryMethod {
    public static void main(String[] args) {
        ConcreteFactory1 concreteFactory1 = new ConcreteFactory1();
        Product product = concreteFactory1.newProduct();
        product.show();
        System.out.println("-------------------------------------------");
        ConcreteFactory2 concreteFactory2 = new ConcreteFactory2();
        Product product2 = concreteFactory2.newProduct();
        product2.show();
    }
}

abstract class Product {//定義了產品的規范,描述了產品的主要特性和功能

    abstract void show();
}

class ConcreteProductA extends Product { //具體產品ProductA

    @Override
    void show() {
        System.out.println("ConcreteProductA");
    }
}

class ConcreteProductB extends Product { //具體產品ProductB

    @Override
    void show() {
        System.out.println("ConcreteProductB");
    }
}

abstract class AbstractFactory{ //提供了創建產品的抽象
    abstract Product newProduct();
}

class ConcreteFactory1 extends AbstractFactory{ //實現抽象工廠中的抽象方法,完成具體產品的創建。

    @Override
    Product newProduct() {
        return  new ConcreteProductA();
    }
}

class ConcreteFactory2 extends AbstractFactory{//實現抽象工廠中的抽象方法,完成具體產品的創建。

    @Override
    Product newProduct() {
        return  new ConcreteProductB();
    }
}
//輸出結果:
ConcreteProductA
-------------------------------------------
ConcreteProductB

工廠方法模式的優點:
用戶只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體創建過程;
在系統增加新的產品時只需要添加具體產品類和對應的具體工廠類,無須對原工廠進行任何修改,滿足開閉原則;

工廠方法模式的缺點:
每增加一個產品就要增加一個具體產品類和一個對應的具體工廠類,這增加了系統的復雜度。

  • AbstractFactory 抽象工廠

模式定義:
定義一個接口,讓該借口負責創建一系列“相關或者相互依賴的對象”,無需指定它們具體的類。

抽象工廠模式是工廠方法模式的升級版本,工廠方法模式只生產一個等級的產品,而抽象工廠模式可生產多個等級的產品。

使用抽象工廠模式條件:
系統中有多個產品族,每個具體工廠創建同一族但屬于不同等級結構的產品。
系統一次只可能消費其中某一族產品,即同族的產品一起使用。

組件:
抽象工廠(AbstractFactory):提供了創建產品的接口,它包含多個創建產品的方法 newProduct(),可以創建多個不同等級的產品。
具體工廠(ConcreteFactory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建。
抽象產品(Product):定義了產品的規范,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來創建,它 同具體工廠之間是多對一的關系。

類圖.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/16-22:38
 */
public class AbstractFactory {
    public static void main(String[] args) {
        ConcreteFactory1 concreteFactory1 = new ConcreteFactory1();
        concreteFactory1.newProduct1().show();
        concreteFactory1.newProduct2().show();
        System.out.println("-----------------------------------------");
        ConcreteFactory2 concreteFactory2 = new ConcreteFactory2();
        concreteFactory2.newProduct1().show();
        concreteFactory2.newProduct2().show();
    }
}
//中國 飛機:J20  航母:遼寧艦
//美國 飛機:F22  航母:福特級航母

abstract class Product1 {  //飛機
    abstract void show();
}

class ConcreteProduct11 extends Product1 {//中國飛機

    @Override
    void show() {
        System.out.println("中國 飛機:J20");
    }
}

class ConcreteProduct12 extends Product1 {//美國飛機:F22

    @Override
    void show() {
        System.out.println("美國 飛機:F22 ");
    }
}

abstract class Product2 {  //航母
    abstract void show();
}

class ConcreteProduct21 extends Product2 {//中國 航母:遼寧艦

    @Override
    void show() {
        System.out.println("中國 航母:遼寧艦");
    }
}

class ConcreteProduct22 extends Product2 {//美國 航母:福特級航母

    @Override
    void show() {
        System.out.println("美國 航母:福特級航母 ");
    }
}

abstract class Factory {
    abstract Product1 newProduct1();

    abstract Product2 newProduct2();
}
class ConcreteFactory1 extends Factory {//中國
    @Override
    Product1 newProduct1() {
        return new ConcreteProduct11();
    }

    @Override
    Product2 newProduct2() {
        return new ConcreteProduct21();
    }

}

class ConcreteFactory2 extends Factory {//美國
    @Override
    Product1 newProduct1() {
        return new ConcreteProduct12();
    }

    @Override
    Product2 newProduct2() {
        return new ConcreteProduct22();
    }

}
//輸出結果:
中國 飛機:J20
中國 航母:遼寧艦
-----------------------------------------
美國 飛機:F22 
美國 航母:福特級航母 

抽象工廠模式除了具有工廠方法模式的優點外,其他主要優點如下:
可以在類的內部對產品族中相關聯的多等級產品共同管理,而不必專門引入多個新的類來進行管理。
當增加一個新的產品族時不需要修改原代碼,滿足開閉原則。

抽象工廠模式缺點:
當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。

  • Prototype 原型模式
    模式定義:
    使用原型實例指定創建對象的種類,然后通過拷貝這些原型來創建新的對象

原型模式組件:
抽象原型類:規定了具體原型對象必須實現的接口。
具體原型類:實現抽象原型類的 clone() 方法,它是可被復制的對象。
訪問類:使用具體原型類中的 clone() 方法來復制新的對象。

類圖.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/17-21:48
 */
public class Prototype {
    public static void main(String[] args) throws CloneNotSupportedException {
        Realizetype realizetype = new Realizetype();
        Realizetype clone = (Realizetype)realizetype.clonePrototype();
        System.out.println("realizetype==clone?  "+ (realizetype==clone));
    }
}


abstract class AbstractPrototype implements Cloneable{
    abstract Object clonePrototype() throws CloneNotSupportedException;
}
class Realizetype  extends   AbstractPrototype{
    Realizetype(){
        System.out.println("Real  King of Monkey");
    }
    Object clonePrototype() throws CloneNotSupportedException {
        System.out.println("fake King of Monkey");
        return (Realizetype)super.clone();
    }
}

//輸出結果:
Real  King of Monkey
fake King of Monkey
realizetype==clone?  false

用一個已經創建的實例作為原型,通過復制該原型對象來創建一個和原型相同或相似的新對象。
在這里,原型實例指定了要創建的對象的種類。用這種方式創建對象非常高效,根本無須知道對象創建的細節。

  • Builder 構建器

模式定義:
將一個復雜對象的構建與其表示相分離,使得同樣的構建過程(穩定)可以創建不同的表示(變化)。

建造者(Builder)模式組件:
產品角色(Product):它是包含多個組成部件的復雜對象,由具體建造者來創建其各個滅部件。
抽象建造者(Builder):它是一個包含創建產品各個子部件的抽象方法的接口,通常還包含一個返回復雜產品的方法 getResult()。
具體建造者(ConcreteBuilder):實現 Builder接口,完成復雜產品的各個部件的具體創建方法。
指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成復雜對象的創建,在指揮者中不涉及具體產品的信息。

類圖.png
package com.lillcol.designmodel;

/**
 * @author lillcol
 * 2019/6/17-22:32
 */
//組裝電腦
public abstract class Builder {
    Product product = new Product();

    abstract void buyKey();

    abstract void buyMouse();

    abstract Product returnComputer();
}


class ConcreteBuilder1 extends Builder {

    @Override
    void buyKey() {
        product.setKey("ConcreteBuilder1 key :雙飛燕無線鼠標");
    }

    @Override
    void buyMouse() {
        product.setMouse("ConcreteBuilder1 mouse :雙飛燕機械鍵盤");
    }

    @Override
    Product returnComputer() {
        return product;
    }
}

class ConcreteBuilder2 extends Builder {

    @Override
    void buyKey() {
        product.setKey("ConcreteBuilder1 key :無線鼠標");
    }

    @Override
    void buyMouse() {
        product.setMouse("ConcreteBuilder1 mouse :雷柏機械鍵盤");
    }

    @Override
    Product returnComputer() {
        return product;
    }
}

class Product {
    String key;

    String mouse;

    public void setKey(String key) {
        this.key = key;
    }

    public void setMouse(String mouse) {
        this.mouse = mouse;
    }

    public void show() {
        System.out.println(key + "    " + mouse);
    }
}

class Director {
    Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buyKey();
        builder.buyMouse();
        return builder.returnComputer();
    }

}

class BuilderTest {
    public static void main(String[] args) {
        ConcreteBuilder1 concreteBuilder1 = new ConcreteBuilder1();
        Director dirctor = new Director(concreteBuilder1);
        Product product = dirctor.construct();
        product.show();
        System.out.println("-----------------");
        ConcreteBuilder2 concreteBuilder2 = new ConcreteBuilder2();
        Director dirctor2 = new Director(concreteBuilder2);
        Product product2 = dirctor2.construct();
        product2.show();

    }
}

//輸出結果:
ConcreteBuilder1 key :雙飛燕無線鼠標    ConcreteBuilder1 mouse :雙飛燕機械鍵盤
-----------------
ConcreteBuilder1 key :無線鼠標    ConcreteBuilder1 mouse :雷柏機械鍵盤

優點:

  1. 各個具體的建造者相互獨立,有利于系統的擴展。
  2. 客戶端不必知道產品內部組成的細節,便于控制細節風險。

缺點:

  1. 產品的組成部分必須相同,這限制了其使用范圍。
  2. 如果產品的內部變化復雜,該模式會增加很多的建造者類。

參考文檔:
http://c.biancheng.net/view/1364.html
李建忠23中設計模式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容