1. 程式人生 > 實用技巧 >java設計模式 23種設計模式和思想

java設計模式 23種設計模式和思想

設計模式

1.、概述

​ 設計模式不是一種語法上的規定,而是一種思想,是解決特定場景問題所總結出的一系列方法,可以靈活運用在我們實際開發中,提高我們程式碼的擴充套件性,可讀性,穩健性,和複用性,從而使我們編寫的程式碼更加穩健和安全

1995年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。這幾位作者常被稱為"四人組(Gang of Four)",而這本書也就被稱為"四人組(或 GoF)"書。共收錄了23中設計模式,是我們軟體設計模式領域的里程碑

就java體系來說,GOF是Java基礎知識和j2EE框架架知識之間一座隱性的,我們都是知道抽象類和介面是java的核心思想,而這些設計模式便是轉換你抽象的思維,從而提高你抽象的能力,進而靈活運用在程式碼編輯中。

​ *** 思想的轉變,還是要體現在日常開發中,這樣,我們才能 更好的體會這些思想帶給我們的便利之處**

2、OOP七大原則

2.1、 開閉原則:對擴充套件開放,對修改關閉

​ 這裡所指的就是我們設計模式的核心思想了,這種模式要求我們,在程式碼設計上,在不修改原始碼的情況下,去增加功能,減小耦合性,再就是上面提到的擴充套件性了,基本上我們所有的設計模式,都是圍繞這個思想進行展開的,

2.1、里氏替換原則:繼承需保證超類中特性在子類中依然成立

​ 繼承有很多的優點,但是也有缺點,採用里氏替換的原則就是增強程式的健壯性,版本升級時也可以保持非常好的相容性。即使增加子類,原有的子類還可以繼續執行。在實際專案中,每個子類對應不同的專案含義,使用父類作為引數,傳遞不同子類完成不同邏輯,非常完美!我們這個就比較好理解了,比如我們的陣列,是線性表結構的表現,是很多資料結構類的超類,所以它的特性,在其他類中也都是存在的,其它類也都具有這個特性

2.2、依賴倒置原則:面向介面程式設計,而不是面向實現程式設計

​ 高層模組不應該依賴低層模組,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象

​ 萬物皆物件,只要是物件,那便是由分類的,抽象類的表示是 has a ,介面則是 is a ,但是我們在具體的實現上,大多數情況中,介面可以對有共同特性的類抽離出來,面向抽象程式設計,而不是面向實現程式設計,從而減小耦合度

2.3、單一職責:控制類的粒度大小,將物件解耦,從而提高內聚性

​ 在日常開發中,其實就有再做這件事情,我們會把程式碼進行抽離成不同的類,進而使他們各自具有不同的功能,互不影響,依賴,這樣在我們系統後期擴充套件,改造當中,也會減少大量的工作

2.4、介面隔離原則:為不同的類,建立它們需要的專有介面

​ 不要強迫客戶程式依賴於自己不需要的介面方法,一個介面只提供一個額定的功能,不應該把所有操作都封裝到一個類中,根據具有共同特性的類,為他們提供專屬他們的介面,這樣在後期對這類功能做出擴充套件的時候,遵守介面定義,提高內聚性

2.5、迪米特法則:只與你的朋友交談,不與 '陌生人說話'

​ 一個物件應該和其他物件的關聯越少越好,物件關聯越多,耦合度就越高,如果類和類之間特定場景下需要關聯,則可以通過一箇中間類來實現這個功能,而不是將這兩個類關聯起來,就好像生活中我們的介面卡是一樣

2.6 、合成複用原則:優先使用組合或聚合關係來實現,其次才考慮繼承關係來實現

​ 新的物件通過關聯關係,使用一些其他已存在的類物件,將它們各自擁有的功能,變為新物件的一部分,如果使用繼承,會破壞系統原有的架構和維護的複雜度,維持類原有的封裝性,提高複用的靈活性

3、建立型模式

單例模式,工廠模式,抽象工廠模式,建造者模式,原型模式

3.1、單例模式

1. 保證類例項只有一個

2. 懶漢模式和餓漢模式
package cn.hhw.designModel.factory.single;

/**
 * Author: jyh
 * Date: 2020/8/27 22:31
 * Content:電腦產品類,   保證物件的例項只有一個,減少系統資源的消耗,
 * spring IOC思想 就是運用了這樣的設計模式,和原型模式來管理bean例項
 * 		餓漢模式
 * 餓漢,見名直意,就是類一開始就存在
 * 1.構造方法私有化
 * 2.建立靜態類例項,在類被載入的時候就建立
 * 3.增加一個靜態方法,返回類例項給呼叫者
 */
public  class Computer {

    private String CPU;
    private String memory;
    private String disk;
    private String monitor;

    private static Computer computer=new Computer();
    //將構造方法私有,通過類內部返回一個類例項物件
    private Computer() {
    }

    public static Computer getInstants(){
        return computer;
    }

}


package cn.hhw.designModel.factory.single;

/**
 * Author: jyh
 * Date: 2020/8/27 22:31
 * Content:電腦產品類,   保證物件的例項只有一個,減少系統資源的消耗,
 * spring IOC思想 就是運用了這樣的設計模式,和原型模式來管理bean例項
 * 
 *  懶漢模式    不提前建立類例項,當有呼叫者需要使用的時候,再建立
 * 1.構造方法私有化
 * 2.將物件例項 加 修飾volatile 保證在多執行緒下資料可見性的安全性,物件的例項永遠只有一個
 * 3.增加一個靜態方法,返回類例項給呼叫者
 * 4.將方法加同步鎖,DCL   雙重檢查,防止多執行緒下產生的執行緒安全問題
 */
public  class Computer2 {

    private String CPU;
    private String memory;
    private String disk;
    private String monitor;

    //讓物件在多執行緒中可見性,禁止指令重排序
    private static volatile Computer2 computer;

    //將構造方法私有,通過類內部返回一個類例項物件
    private Computer2() {
    }

    //DCL 雙重檢查
    public static  Computer2 getInstants(){
        if(computer == null){
            synchronized(Computer2.class) {
                if(computer == null) {
                    return new Computer2();
                }
            }
        }
        return computer;
    }

}

結語:餓漢模式比較簡單,沒有執行緒安全問題。但懶漢模式存線上程安全問題,當同一時間多個執行緒去進入getInstant方法時,可能會建立多個類例項,所以我們需要加鎖,而當我們加了synchoronized 同步鎖之後,雖然不會再出現這樣的問題,但是鎖的粗度太大了,以後每個執行緒進這個方法都要阻塞等待,其實我們只需要保證前幾次的執行緒進入方法時,不出現問題,當類還沒完成建立的時候,同時有兩個執行緒進入非空校驗,之後有一個執行緒獲得鎖,創建出例項,這個時候另外一個執行緒也拿到鎖,但當它拿到鎖之後,會再次進行非空判斷,發現物件已經被建立過了,便會直接類例項物件,而後面再來的執行緒根本就不會進入鎖,所以用一種巧妙DCL的方式,解決了多執行緒下的安全問題

3.2、工廠模式

	1、 實現建立者和呼叫者的分離,用工廠方法代替原有的new

	2、將物件的建立統一管理和控制,從而讓呼叫者和我們的實現類解耦
3.2.1、簡單工廠模式
	- 用於生產同一等級結構內的任意產品
package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:定義一個車的介面,用來規範
 */
public interface Car {
    void getCarName();
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:50
 * Content:
 */
public class AodiCar  implements Car{
    @Override
    public void getCarName() {
        System.out.println("五菱巨集光");
    }
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:
 */
public class DazhongCar implements Car{

    @Override
    public void getCarName() {
        System.out.println("大眾車");
    }
}
package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:54
 * Content:
 * 將物件的建立,交給工廠類來建立,統一管理同一類例項
 * 缺點,當我們需要新增 新的車時,還是需要增加方法,修改原有程式碼 違背了開閉原則
 */
public class FactoryCar {

    public static  DazhongCar produDazhongCar(){
        return new DazhongCar();
    }
    public static AodiCar produAodiCar(){
        return new AodiCar();
    }
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:51
 * Content: 消費者
 * 1. 簡單工廠模式,可以代替使用者直接new物件的方式,而是通過外部的車工廠類去建立不同車的類,但是,當我們要增加新的車時,必須要在車工廠
 *  類裡新增方法,修改了原有的類和程式碼, 這樣的方式,違背了我們設計模式的開閉原則,可以擴充套件,不可以修改
 */
public class Consumer {
    public static void main(String[] args) {
//        Car dazhongCar = new DazhongCar();
//        Car dadoCar = new AodiCar();
//        dazhongCar.getCarName();
//        dadoCar.getCarName();
        Car dazhongCar = FactoryCar.produDazhongCar();
        Car aodiDaCar= FactoryCar.produAodiCar();
        dazhongCar.getCarName();
        aodiDaCar.getCarName();
    }
}

結語:簡單工廠模式,可以代替使用者直接new物件的方式,而是通過外部的車工廠類統一去建立不同車的類例項,但是,當我們要增加新的車時,必須要在車工廠
類裡新增方法,修改了原有的類和程式碼, 這樣的方式,違背了我們設計模式的開閉原則,可以擴充套件,不可以修改

3.2.1、工廠方法模式

用來生產同一等級結構中的固定型別產品

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:定義一個車的介面,用來規範
 */
public interface Car {
    void getCarName();
}

public class WuLingCar implements Car {
    @Override
    public void getCarName() {
        System.out.println("五菱巨集光");
    }
}
public class DazhongCar implements Car {

    @Override
    public void getCarName() {
        System.out.println("大眾車");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:02
 * Content: 車工廠介面,使用者可以根據不同分類的車,去構建自己的對應車工場
 */
public interface Factory {
        Car CreateCar();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:03
 * Content:大眾車廠
 */
public class DazhongFactory implements Factory {
    @Override
    public Car CreateCar() {
        return new DazhongCar();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:20
 * Content:五菱巨集光車廠
 */
public class WuLingFactory implements Factory {
    @Override
    public Car CreateCar() {
        return new WuLingCar();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:05
 * Content:使用者可以選擇不同的車工場,去獲得資金想要的車。
 * 1.車工廠介面,2.不同車的工廠實現 3.車的工廠。4.不同車的實現
 * 使用者需要什麼車,便去獲取什麼車工廠。這樣實現了,在不修改原始碼的情況下,動態擴充套件
 */
public class Consumer {

    public static void main(String[] args) {
        DazhongFactory dazhongFactory = new DazhongFactory();
        Car dazhongcar = dazhongFactory.CreateCar();
        AodiFactory aodiFactory = new AodiFactory();
        Car aodicarCar = aodiFactory.CreateCar();
        dazhongcar.getCarName();
        aodicarCar.getCarName();
        WuLingFactory wuLingFactory = new WuLingFactory();
        Car car = wuLingFactory.CreateCar();
        car.getCarName();

    }
}

結語:我們對車工廠也提取了一個介面,這樣實現了再增加新的車的時候,不需要修改原有類,只需要動態的增加對應的車和車工廠即可

符合開閉原則,解決了簡單工廠的問題,但實際觀察下來,程式碼複雜度太高了,類一直在增加,簡單工廠雖然某種程度上不符合設計原則,但實際使用卻是最多的

3.3、抽象工廠模式

圍繞一個超級工廠,建立其他工廠,又稱為其他工廠的工廠

/**
 * Author: jyh
 * Date: 2020/8/27 21:10
 * Content:手機介面
 */
public interface Phone {
    //開機
    void start();
    //關機
    void shutdown();
    //發簡訊
    void sedMes();
    //打電話
    void call();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:15
 * Content:路由器介面
 */
public interface Routers {
    //開機
    void start();
    //關機
    void shutdown();
    //開始wifi
    void Wifi();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:12
 * Content:華為手機
 */
public class HuaWeiPhone implements Phone {
    @Override
    public void start() {
        System.out.println("華為手機開機");
    }

    @Override
    public void shutdown() {
        System.out.println("華為手機關機");
    }

    @Override
    public void sedMes() {
        System.out.println("華為手機發簡訊");
    }

    @Override
    public void call() {
        System.out.println("華為手機打電話");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:13
 * Content:小米手機
 */
public class XiaoMiPhone implements Phone {
    @Override
    public void start() {
        System.out.println("小米手機開機");

    }

    @Override
    public void shutdown() {
        System.out.println("小米手機關機");

    }

    @Override
    public void sedMes() {
        System.out.println("小米手機發簡訊");

    }

    @Override
    public void call() {
        System.out.println("小米手機打電話");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:23
 * Content:華為路由器
 */
public class HuaweiRouter implements Routers {
    @Override
    public void start() {
        System.out.println("華為路由器開機");
    }

    @Override
    public void shutdown() {
        System.out.println("華為路由器關機");

    }

    @Override
    public void Wifi() {
        System.out.println("華為路由器開啟wifi");

    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:23
 * Content:小米路由器
 */
public class XiaoMiRouter implements Routers {
    @Override
    public void start() {
        System.out.println("小米路由器開機");
    }

    @Override
    public void shutdown() {
        System.out.println("小米路由器關機");

    }

    @Override
    public void Wifi() {
        System.out.println("小米路由器開啟wifi");

    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:24
 * Content: 產品工廠介面,只提供生產產品的定義,具體需要生產哪類產品,需要產品廠家自己增加實現
 */
public interface ProductFatory  {
    Phone gePhone();
    Routers getRouters();

}
/**
 * Author: jyh
 * Date: 2020/8/27 21:29
 * Content: * Content:華為的產品工廠,用來生產華為的產品
 */
public class HuaweiFactory implements ProductFatory {
    @Override
    public Phone gePhone() {
        return new HuaWeiPhone();
    }

    @Override
    public Routers getRouters() {
        return new HuaweiRouter();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:29
 * Content:小米的產品工廠,用來生產小米的產品
 */
public class XiaoMiFactory implements ProductFatory {
    @Override
    public Phone gePhone() {
        return new XiaoMiPhone();
    }

    @Override
    public Routers getRouters() {
        return new XiaoMiRouter();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:30
 * Content:使用者在需要使用哪家產品的時候,只需要建立哪家的廠家即可
 */
public class Consomer {
    public static void main(String[] args) {
        //華為工廠
        HuaweiFactory huaweiFactory = new HuaweiFactory();
        //獲得華為手機
        Phone huaweiphone = huaweiFactory.gePhone();
        huaweiphone.start();
        huaweiphone.shutdown();
        huaweiphone.sedMes();
        huaweiphone.call();
        //獲得華為路由器
        Routers huaweirouRouters = huaweiFactory.getRouters();
        huaweirouRouters.start();
        huaweirouRouters.shutdown();
        huaweirouRouters.Wifi();
        System.out.println("=====================================================");
        //小米工廠
        XiaoMiFactory xiaomiFactory = new XiaoMiFactory();
        //獲得小米手機
        Phone xiaomiphone = xiaomiFactory.gePhone();
        xiaomiphone.start();
        xiaomiphone.shutdown();
        xiaomiphone.sedMes();
        xiaomiphone.call();
        //獲得小米路由器
        Routers xiaomirouRouters = xiaomiFactory.getRouters();
        xiaomirouRouters.start();
        xiaomirouRouters.shutdown();
        xiaomirouRouters.Wifi();
    }
}

結語:抽象工廠模式是對應產品工廠介面,只提供生產產品的定義,具體需要生產哪類產品,需要產品廠家自己增加實現,這樣的的設計模式,可以擴展出不同的產品族,但不能再增加產品,因為產品介面已經定義好了,比如我們可以增加蘋果路由器,蘋果手機,和蘋果工廠,這樣動態擴充套件即可,不需要修改原始碼便可以實現

工廠模式應用場景:

	- JDK的calendar的genInstance方法
	- jdbc的connection物件獲取
	- springIOC容器建立管理bean物件
	- 反射中Class物件的newInstance

3.4、建造者模式

3.4.1、指揮者存在內部

​ 提供了一種建立物件的最佳方式,將一個複雜的物件建立與它的表示分析,使得同樣的構建過程可以建立不同的表示

/**
 * Author: jyh
 * Date: 2020/8/27 22:55
 * Content:模擬複雜類
 */
public class Product {
    private String executeA;
    private String executeb;
    private String executec;
    private String executed;

    public String getExecuteA() {
        return executeA;
    }

    public void setExecuteA(String executeA) {
        this.executeA = executeA;
    }

    public String getExecuteb() {
        return executeb;
    }

    public void setExecuteb(String executeb) {
        this.executeb = executeb;
    }

    public String getExecutec() {
        return executec;
    }

    public void setExecutec(String executec) {
        this.executec = executec;
    }

    public String getExecuted() {
        return executed;
    }

    public void setExecuted(String executed) {
        this.executed = executed;
    }

    @Override
    public String toString() {
        return "Product{" +
                "executeA='" + executeA + '\'' +
                ", executeb='" + executeb + '\'' +
                ", executec='" + executec + '\'' +
                ", executed='" + executed + '\'' +
                '}';
    }
}
package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 22:57
 * Content: 建造者的介面定義
 */
public abstract  class  Executer {

    //建造步驟1.
    abstract void executeA();
    //建造步驟2.
    abstract void executeB();
    //建造步驟2.
    abstract void executeC();
    //建造步驟3.
    abstract void executeD();
    //建造步驟4.
    abstract Product getProduct();
}

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 22:59
 * Content:實際真實的建造者,可以有多個建造者
 */
public class Worker extends Executer {
    private Product product;

    //此步為關鍵,實際複雜物件的例項化必須要有建造者完成。最終返回
    public Worker() {
        this.product = new Product();
    }

    //建造步驟1.打地基
    @Override
    void executeA() {
        product.setExecuteA("地基");
        System.out.println("地基");
    }

    //建造步驟2.鋪地板
    @Override
    void executeB() {
        product.setExecuteA("地板");
        System.out.println("地板");
    }
    //建造步驟3.裝傢俱
    @Override
    void executeC() {
        product.setExecuteA("裝傢俱");
        System.out.println("裝傢俱");
    }

    //建造步驟3.貼瓷磚
    @Override
    void executeD() {
        product.setExecuteA("貼瓷磚");
        System.out.println("貼瓷磚");
    }

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

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 23:10
 * Content:指揮者,指揮建造者構建複雜物件,可以控制建造者建造的過程
 */
public class Leader {

    //傳入一個建造者,指揮建造者建造出類,進行返回,此處模擬建房子步驟
    public Product Product(Executer executer){
        executer.executeB();
        executer.executeA();
        executer.executeC();
        executer.executeD();
        return executer.getProduct();
    }
}

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 23:13
 * Content:呼叫者,需要一個物件例項
 */
public class Test {
    public static void main(String[] args) {
        //建立指揮者,通過指揮者呼叫建造者,生產物件
        Leader leader = new Leader();
        Product product = leader.Product(new Worker());
        System.out.println(product);
    }
}

上述事例是Builder常規用法,在使用者不知道物件的建造過程和細節的情況下就可以直接完成建立複雜物件,建造和表示分離,實現解耦,建立步驟分解在不同的方法中,使得建立過程更加清晰,具體的建造者類之間是相互獨立的,有利於系統擴充套件,增加新的建造者,也不需要修改原有類庫,符合‘開閉原則’

3.4.2、指揮權交給使用者
package cn.hhw.designModel.factory.builder.demo3;

/**
 * Author: jyh
 * Date: 2020/8/27 23:15
 * Content:複雜產品類
 */
public class Hamburger {
    private String hanbao = "漢堡";
    private String drink = "飲料";
    private String chip ="薯條";
    private String cheese="乳酪";


    @Override
    public String toString() {
        return "Hamburger{" +
                "hanbao='" + hanbao + '\'' +
                ", drink='" + drink + '\'' +
                ", chip='" + chip + '\'' +
                ", cheese='" + cheese + '\'' +
                '}';
    }

    public String getHanbao() {
        return hanbao;
    }

    public void setHanbao(String hanbao) {
        this.hanbao = hanbao;
    }

    public String getDrink() {
        return drink;
    }

    public void setDrink(String drink) {
        this.drink = drink;
    }

    public String getChip() {
        return chip;
    }

    public void setChip(String chip) {
        this.chip = chip;
    }

    public String getCheese() {
        return cheese;
    }

    public void setCheese(String cheese) {
        this.cheese = cheese;
    }
}

package cn.hhw.designModel.factory.builder.demo3;

import java.util.HashMap;

/**
 * Author: jyh
 * Date: 2020/8/27 23:17
 * Content:建造者介面
 */
public abstract class Person {

    abstract Person executeA(String hanbao);
    abstract Person executeB(String drink);
    abstract Person executeC(String chip);
    abstract Person executeD(String hanbao);
    abstract  Hamburger gethamburger();
}

package cn.hhw.designModel.factory.builder.demo3;

import java.util.HashMap;

/**
 * Author: jyh
 * Date: 2020/8/27 23:19
 * Content:實際建造者
 */
public class Waiter extends Person{
    private Hamburger hanHamburger;


    public Waiter(){
        hanHamburger=new Hamburger();
    }

    @Override
    Waiter executeA(String hanbao) {
        hanHamburger.setHanbao(hanbao);
        System.out.println(hanbao);
        return this;
    }

    @Override
    Waiter executeB(String drink) {
        hanHamburger.setHanbao(drink);
        System.out.println(drink);
        return this;
    }

    @Override
    Waiter executeC(String chip) {
        hanHamburger.setHanbao(chip);
        System.out.println(chip);
        return this;
    }

    @Override
    Waiter executeD(String cheese) {
        hanHamburger.setHanbao(cheese);
        System.out.println(cheese);
        return this;
    }

    @Override
    Hamburger gethamburger() {

        return hanHamburger;
    }


}

package cn.hhw.designModel.factory.builder.demo3;

/**
 * Author: jyh
 * Date: 2020/8/27 23:26
 * Content:指揮者
 */
public class Consumer {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        //鏈式程式設計
       // waiter.executeA("雞腿皇堡").executeB("可樂兩杯").executeC("巧克力乳酪");
        waiter.executeA("雞腿皇堡");
        waiter.executeB("可樂兩杯");
        waiter.executeC("巧克力乳酪");

        //這裡要是執行D步驟,就是預設值
        Hamburger gethamburger = waiter.gethamburger();
        System.out.println(gethamburger);
    }
}


結語:指揮者在建造者模式中有重要的作用,通常是知道建造者如何構建產品,並向建造者返回完整的產品,有時是可以簡化的,通常會把指揮的權利交給使用者,通過靜態內部類的方式實現零件無需裝配構造,這種方式更加靈活,也更符合定義,內部類有複雜物件的預設實現,使用時可以根據需求自由更改內容,無需改變具體的構造方法,就可以生產出不同的複雜產品 缺點是如果產品內部變化複雜,就需要定義很多具有建造者,導致系統變得很龐大

3.5、原型模式

protoType

對複雜類的直接克隆引用,減少重新構建過程

package cn.hhw.designModel.factory.cloneModel;

import java.util.Date;

/**
 * Author: jyh
 * Date: 2020/8/28 20:45
 * Content:需要被克隆的類
 * 1.實現cloneable 表示 這個類可以被克隆
 * 在不實現Cloneable介面的例項上呼叫物件的克隆方法導致丟擲異常CloneNotSupportedException 。
 * 2.重寫父類的object方法
 */
public class User implements Cloneable {
    private int id;
    private String name;
    private Date birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User clone = (User)super.clone();
        clone.birthday.clone();
        return  clone;

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

package cn.hhw.designModel.factory.cloneModel;

import javax.sound.midi.Soundbank;
import java.util.Date;

/**
 * Author: jyh
 * Date: 2020/8/28 20:49
 * Content:
 */
public class Test  {
    public static void main(String[] args) throws CloneNotSupportedException {
        //此處有一個問題,如果改變原物件的id,name,克隆物件,並不會改變,但如果改變了原物件的birthday,那麼clone物件的這個欄位值
        //也會改變。原因是date是引用的,所以需要將在類中將date也克隆
        Date date = new Date();
        User user1 = new User();
        user1.setId(1);
        user1.setName("zhangsan");
        user1.setBirthday(date);
        System.out.println(user1);
        System.out.println("========================================");
        User user2 = (User) user1.clone();
        System.out.println(user2);

        user1.setBirthday(date);
        user1.setName("wangwu");
        System.out.println(user1);
        System.out.println(user2);

    }
}

原型模式就是對一個構建好的物件進行直接複製,然後使用,減少了一些複雜的構建過程,提高了複用性

4、結構型模式

介面卡模式,

將一個類的介面轉換成客戶希望的另外一個介面,使得原本不相容不可以在一起工作的類可以在一起工作

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:25
 * Content: Target 網線,可以上網
 */
public class Intel {

    public void connectionNetwork(){

        System.out.println("可以上網啦!!!!(*^▽^*)");
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:28
 * Content:類介面卡,繼承網線類,則有網線的上網方法
 *物件介面卡
 */
public class Adapter extends Intel {

    @Override
    public void connectionNetwork() {
        super.connectionNetwork();
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:24
 * Content:膝上型電腦,需要連線到網線類,但是介面不同,不能直接使用,需要一箇中間介面卡類來完成這個動作
 */
public class Laptop {
    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        //連線到介面卡
        connectAdap(adapter);
    }
    
    public static void  connectAdap( Adapter adapter){
        adapter.connectionNetwork();
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:28
 * Content:類介面卡,繼承網線類,則有網線的上網方法
 *物件介面卡 對於不同的要求,則使用不同的物件進行處理
 * 介面卡,其實應該定義為介面
 */
public class Adapter  {

    private Intel intel;

    public Adapter() {
        this.intel = new Intel();
    }


    public void connectionNetwork() {
        intel.connectionNetwork();
    }
}

結語:三種角色定義,目標介面,使用者所需要連線到的真正目標類,可以是具體的實現,也可以是抽象類或介面,就好像使用者需要上網,這個目標就是網線類

需要適配的類,這裡對應的就是電腦,電腦需要適配,那電腦就是需要被適配的類

介面卡:通過包裝一個需要適配的物件,吧源介面轉換成目標物件

一個物件介面卡可以把多個不同的適配者配到同一個目標

橋接模式,裝飾模式,組合模式,外觀模式,享元模式,代理模式

5、行為型模式

模板方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、直譯器模式、狀態模式、策略模式、職責鏈模式、訪問者模式