設計模式--簡化解釋(一)——建立型設計模式

1.建立型設計模式
2.結構型設計模式
3.行爲型設計模式java

建立型設計模式

簡而言之面試

建立型設計模式關注的是如何實例化一個或者一組相關的對象。

維基百科編程

在軟件工程中,建立型設計模式是用於解決對象建立機制,嘗試在指定場景下使用合理的方式來建立對象的設計模式。基本的建立方式對致使設計問題或者增長設計的複雜度。建立型設計模式經過一些控制對象建立的手段來解決這些問題。

? 簡單工廠

現實例子segmentfault

考慮一下,你須要建造一個房子,而後須要幾扇門。若是每次須要一扇門的時候,你都穿上木匠的衣服而後在房間裏左門會形成很大的混亂。取而代之是你須要買一個從工廠裏作好的。

簡而言之設計模式

對客戶端來講,簡單工廠模式僅僅生成一個實例,不須要暴露給客戶端人戶實例化的邏輯。

維基百科說ide

在面向對象編程中(OOP),工廠是一個用於建立對象的對象,正式的工廠是一個方法或者函數,在某些方法調用的時候返回不一樣的原型或者對象,咱們認爲這個對象是新的。

編程實例
首先咱們有一個們的接口和實現函數

public interface Door {
    float getWidth();
    float getHeight();
}
public class WoodenDoor implements Door {
    private float width;
    private float height;

    public WoodenDoor(float width, float height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public float getWidth() {
        return 0;
    }

    @Override
    public float getHeight() {
        return 0;
    }
}

而後咱們須要一個生產並返回門的工廠ui

public class DoorFactory {
    public static Door makeDoor(float width,float height)
    {
        return new WoodenDoor(width,height);
    }
}

使用方式以下this

Door door = DoorFactory.makeDoor(1200L,2100L);
System.out.println("Door Width:"+door.getWidth());
System.out.println("Door Height:"+door.getHeight());

什麼時候使用
當建立一個不只僅是幾條賦值語句同時包含一些邏輯的對象的時候,把建立對象的代碼放到一個專用的工廠中而不是處處賦值相同的代碼,這是情理之中的。翻譯

? 工廠方法

現實例子

考慮一我的事部經理的例子. 不可能全部的崗位都有一我的來面試. 根據職位空缺,他將面試的步驟安排給不一樣的人.

簡而言之

提供一種將實例化邏輯委託給子類的方式.

維基百科說

在給予類的編程中,工廠方法模式是一個建立型的模式,這個模式用於解決建對象的問題而無需指定要建立的精確的類。經過調用工廠方法(在接口中指定並由子類實現,或者在基類中實現),或者經過派生類(而不是調用構造函數)來實現,這是經過建立對象來完成的。

編程示例
參考上邊人事部經理的例子。首先咱們有一個面試官的接口和一些實現。

public interface Inteviewer {
    void askQuestions();
}
public class Developer implements Inteviewer {
    @Override
    public void askQuestions() {
        System.out.println("Ask about Design Patterns");
    }
}
public class CommunityExecutive implements Inteviewer {
    @Override
    public void askQuestions() {
        System.out.println("Ask about community build");
    }
}

如今咱們建立 HiringManager

public abstract class HiringManager {
    protected abstract Inteviewer makeInteviewer();

    public void takeInteview()
    {
        Inteviewer inteviewer = makeInteviewer();
        inteviewer.askQuestions();
    }
}

如今和人子類均可以實現該類來提供須要的面試官

public class DevelopmentManager extends HiringManager {
    @Override
    protected Inteviewer makeInteviewer() {
        return new Developer();
    }
}
public class CommunityManager extends HiringManager {
    @Override
    protected Inteviewer makeInteviewer() {
        return new CommunityExecutive();
    }
}

使用舉例

public class Client {
    public static void main(String[] args) {
        HiringManager manager = new DevelopmentManager();
        manager.takeInteview();

        manager = new CommunityManager();
        manager.takeInteview();
    }
}

什麼時候使用?
當一個類中有一些通用的處理可是子類須要在運行時決定的時候使用。換句話說,客戶端不知道須要的精確的子類。

? 抽象工廠

現實舉例

擴展咱們的簡單工廠模式的門的例子。考慮到你的需求,你可能從一個木門的商店購買一個木門,從一個鐵門的商店購買一個鐵門,或者從另外的相關的商店購買一個PVC門。除此以外你可能須要一個有不一樣技能的夥計幫你裝門,例如木匠來裝木門,焊接工裝鐵門。正如你看到的那樣,如今門之間有一個依賴,木門須要木匠,鐵門須要焊接工等等。

簡而言之

一個工廠的工廠。一個工廠在不指定具體的類的狀況下將獨立但相關的工程組合在一塊兒。

維基百科說

抽象工廠模式提供了一種方式來封裝一度獨立的工廠,這些工廠有相同的主題當時沒有指定具體的類。

編程示例

翻譯上邊門的例子. 首先咱們有門的接口和幾個門的實現

public interface Door {
    String getDescription();
}
public class WoodenDoor implements Door {
    @Override
    public String getDescription() {
        return "I am a wooden door";
    }
}
public class IronDoor implements Door {
    @Override
    public String getDescription() {
        return "I am an iron door";
    }
}

而後每一種門咱們有一些安裝專家

public interface DoorFittingExpert {
    String getDescription();
}
public class Carpenter implements DoorFittingExpert {
    @Override
    public String getDescription() {
        return "I can only fit wooden doors";
    }
}
public class Welder implements DoorFittingExpert {
    @Override
    public String getDescription() {
        return "I can only fit iron doors";
    }
}

如今咱們須要一個抽象工廠來幫咱們決定相關對象的族。例如木門工廠須要生產木門和木門安裝專家,鐵門工廠須要生產鐵門和鐵門安裝專家。

public interface DoorFactory {
    Door makeDoor();
    DoorFittingExpert makeFittingExper();
}
public class WoodenDoorFactory implements DoorFactory {
    @Override
    public Door makeDoor() {
        return new WoodenDoor();
    }

    @Override
    public DoorFittingExpert makeFittingExper() {
        return new Carpenter();
    }
}
public class IronDoorFactory implements DoorFactory {
    @Override
    public Door makeDoor() {
        return new IronDoor();
    }

    @Override
    public DoorFittingExpert makeFittingExper() {
        return new Welder();
    }
}

使用方式以下:

DoorFactory doorFactory = new WoodenDoorFactory();
        Door door = doorFactory.makeDoor();
        DoorFittingExpert expert = doorFactory.makeFittingExper();
        System.out.println("Door:"+door.getDescription());
        System.out.println("Expert:"+expert.getDescription());

正如上邊看到的同樣,木門工廠封裝了carpenterwooden door,鐵門工廠封裝了iron doorwelder.所以工廠幫咱們確信每個建立的門都不會有錯誤的安裝的專家

什麼時候使用
當有相關的複雜的建立邏輯的依賴的時候

? 建造者

現實舉例

設想一下你在Hardee,你要點餐,咱們會說:Big Hardee,他們不會問任何 問題就會把飯端過來。這是一個簡單工廠的例子。可是有種狀況下建立邏輯包含幾個步驟。例如你想吃一個自助的Subway,漢堡怎麼作,例如麪包用什麼樣的,用什麼樣的醬汁,想要什麼樣的奶酪。這種狀況下,建造者模式將會拯救咱們。

簡而言之

避免構造函數污染的狀況下爲對象創造不一樣的特性。當一個對象有多個特性或者建立對象包含幾個步驟的時候使用。

維基百科說

建造者模式是一種對象建立軟件設計模式,其目的是找到一種解決方案,以解決可伸縮構造函數的反模式。

說道這裏,讓我添加一點關於伸縮構造函數反模式的內容。在某些地方,咱們都看到了以下的構造函數。:

public Deal(int size, boolean cheese ,boolean pepperoni, boolean tomato, boolean lettuce)
{
}

正如你所看到的;構造函數參數的數量很快就會失去控制,而且很難理解參數的排列。另外,若是你想在將來增長更多的選項,這個參數列表還能夠繼續增加。這被稱爲伸縮構造函數反模式。

程序示例
明智的選擇是使用建造者模式。首先咱們要有一個咱們要作的漢堡(burger)

package com.suifeng.designpattern.builder;

public class Burger {
    private int size;
    private boolean cheese;
    private boolean pepperoni;
    private boolean lettuce;
    private boolean tomato;

    public Burger(BurgerBuilder builder)
    {
        this.size = builder.size;
        this.cheese=builder.cheese;
        this.pepperoni = builder.pepperoni;
        this.lettuce = builder.lettuce;
        this.tomato = builder.tomato;
    }

    @Override
    public String toString() {
        return "Burger{" +
                "size=" + size +
                ", cheese=" + cheese +
                ", pepperoni=" + pepperoni +
                ", lettuce=" + lettuce +
                ", tomato=" + tomato +
                '}';
    }

    static class BurgerBuilder{
        private int size;
        private boolean cheese;
        private boolean pepperoni;
        private boolean lettuce;
        private boolean tomato;

        public BurgerBuilder(int size) {
            this.size = size;
        }

        public BurgerBuilder addCheese()
        {
            this.cheese = true;
            return this;
        }

        public BurgerBuilder addPepperoni()
        {
            this.pepperoni = true;
            return this;
        }

        public BurgerBuilder addLettuce()
        {
            this.lettuce = true;
            return this;
        }

        public BurgerBuilder addTomato()
        {
            this.tomato = true;
            return this;
        }

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

使用方式以下

Burger burger = new Burger.BurgerBuilder(12).addCheese().addLettuce().build();
        System.out.println(burger);

什麼時候使用
當一個對象有幾個特性而且須要避免構造器伸縮。與工廠模式的主要不一樣是:工廠模式的建立過程只有一個步驟而建造者模式須要多個步驟。

? 原型

現實舉例

還記得多裏嗎?就是那隻被克隆的山羊。咱們不關注細節,這裏的關鍵就是克隆。

簡而言之

經過克隆的方式根據現有對象來建立新對象

維基百科說

原型模式是軟件開發中的一個建立型設計模式。當要建立的對象類型由一個原型實例決定時,使用原型模式,該實例被克隆以產生新的對象。

簡而言之,它容許您建立一個現有對象的副本,並根據您的須要修改它,而不是從頭開始建立一個對象並設置它。

Programmatic Example

Java中可使用clone方法

public class Sheep implements Cloneable {

    private String name;
    private String category;

    public Sheep(String name, String category) {
        this.name = name;
        this.category = category;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", category='" + category + '\'' +
                '}';
    }

    public Sheep clone()
    {
        Object obj = null;

        try {
            obj =super.clone();

            return (Sheep) obj;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return null;
    }
}

克隆方式以下

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("Jolly","Mountain Sheep");

        Sheep dolly = sheep.clone();
        dolly.setName("Dolly");

        System.out.println(dolly);
    }
}

什麼時候使用?

當須要的對象與存在的對象類似的時候或者相比於克隆建立成本比較高的狀況.

? 單例

現實舉例

同一時間一個國家只有一個總統。 當指責須要的時候,採起行動的是同一個總統. 在這裏總統就是單例的

簡而言之

一個特定的類確保只建立一個對象。

維基百科說

在軟件工程中,單例模式是一種軟件設計模式,它將類的實例化限制爲一個對象。 當須要一個對象來協調整個系統中的操做時,這頗有用。

單例模式實際上被認爲是一種反模式,應該避免過分使用。它並不必定是壞的,而且能夠有一些有效的用例,可是應該謹慎使用,由於它在您的應用程序中引入了一個全局狀態,而且在一個地方對它進行更改可能會影響到其餘領域,所以調試可能變得很是困難。另外一件很差的事情是,它使您的代碼緊密耦合,另外對單例對象的模擬是困難的。

編程示例
建立一個單例,須要將構造函數私有,禁用可控和擴展,經過建立一個靜態的變量來保存實例。

public class President {
    private static President INSTANCE ;

    private President()
    {

    }

    public static President getInstance()
    {
        if(INSTANCE == null)
        {
            INSTANCE = new President();
        }

        return INSTANCE;
    }


}

使用方式以下

President president1 = President.getInstance();
        President president2 = President.getInstance();

        System.out.println(president1 == president2);
相關文章
相關標籤/搜索