java设计模式 23种设计模式和思想
設(shè)計模式
1、概述
? 設(shè)計模式不是一種語法上的規(guī)定,而是一種思想,是解決特定場景問題所總結(jié)出的一系列方法,可以靈活運用在我們實際開發(fā)中,提高我們代碼的擴展性,可讀性,穩(wěn)健性,和復(fù)用性,從而使我們編寫的代碼更加穩(wěn)健和安全
1995年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。這幾位作者常被稱為"四人組(Gang of Four)",而這本書也就被稱為"四人組(或 GoF)"書。共收錄了23中設(shè)計模式,是我們軟件設(shè)計模式領(lǐng)域的里程碑
就java體系來說,GOF是Java基礎(chǔ)知識和j2EE框架架知識之間一座隱性的,我們都是知道抽象類和接口是java的核心思想,而這些設(shè)計模式便是轉(zhuǎn)換你抽象的思維,從而提高你抽象的能力,進而靈活運用在代碼編輯中。
? *思想的轉(zhuǎn)變,還是要體現(xiàn)在日常開發(fā)中,這樣,我們才能 更好的體會這些思想帶給我們的便利之處
2、OOP七大原則
2.1、 開閉原則:對擴展開放,對修改關(guān)閉
? 這里所指的就是我們設(shè)計模式的核心思想了,這種模式要求我們,在代碼設(shè)計上,在不修改原代碼的情況下,去增加功能,減小耦合性,再就是上面提到的擴展性了,基本上我們所有的設(shè)計模式,都是圍繞這個思想進行展開的,
2.2、里氏替換原則:繼承需保證超類中特性在子類中依然成立
? 繼承有很多的優(yōu)點,但是也有缺點,采用里氏替換的原則就是增強程序的健壯性,版本升級時也可以保持非常好的兼容性。即使增加子類,原有的子類還可以繼續(xù)運行。在實際項目中,每個子類對應(yīng)不同的項目含義,使用父類作為參數(shù),傳遞不同子類完成不同邏輯,非常完美!我們這個就比較好理解了,比如我們的數(shù)組,是線性表結(jié)構(gòu)的表現(xiàn),是很多數(shù)據(jù)結(jié)構(gòu)類的超類,所以它的特性,在其他類中也都是存在的,其它類也都具有這個特性
2.3、依賴倒置原則:面向接口編程,而不是面向?qū)崿F(xiàn)編程
? 高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細節(jié),細節(jié)應(yīng)該依賴抽象
? 萬物皆對象,只要是對象,那便是由分類的,抽象類的表示是 has a ,接口則是 is a ,但是我們在具體的實現(xiàn)上,大多數(shù)情況中,接口可以對有共同特性的類抽離出來,面向抽象編程,而不是面向?qū)崿F(xiàn)編程,從而減小耦合度
2.4、單一職責(zé):控制類的粒度大小,將對象解耦,從而提高內(nèi)聚性
?
? 在日常開發(fā)中,其實就有再做這件事情,我們會把代碼進行抽離成不同的類,進而使他們各自具有不同的功能,互不影響,依賴,這樣在我們系統(tǒng)后期擴展,改造當(dāng)中,也會減少大量的工作
2.5、接口隔離原則:為不同的類,建立它們需要的專有接口
? 不要強迫客戶程序依賴于自己不需要的接口方法,一個接口只提供一個額定的功能,不應(yīng)該把所有操作都封裝到一個類中,根據(jù)具有共同特性的類,為他們提供專屬他們的接口,這樣在后期對這類功能做出擴展的時候,遵守接口定義,提高內(nèi)聚性
2.6、迪米特法則:只與你的朋友交談,不與 ‘陌生人說話’
?
? 一個對象應(yīng)該和其他對象的關(guān)聯(lián)越少越好,對象關(guān)聯(lián)越多,耦合度就越高,如果類和類之間特定場景下需要關(guān)聯(lián),則可以通過一個中間類來實現(xiàn)這個功能,而不是將這兩個類關(guān)聯(lián)起來,就好像生活中我們的適配器是一樣
2.7 、合成復(fù)用原則:優(yōu)先使用組合或聚合關(guān)系來實現(xiàn),其次才考慮繼承關(guān)系來實現(xiàn)
? 新的對象通過關(guān)聯(lián)關(guān)系,使用一些其他已存在的類對象,將它們各自擁有的功能,變?yōu)樾聦ο蟮囊徊糠?#xff0c;如果使用繼承,會破壞系統(tǒng)原有的架構(gòu)和維護的復(fù)雜度,維持類原有的封裝性,提高復(fù)用的靈活性
3、創(chuàng)建型模式
單例模式,工廠模式,抽象工廠模式,建造者模式,原型模式
3.1、單例模式
1. 保證類實例只有一個 2. 懶漢模式和餓漢模式 package cn.hhw.designModel.factory.single;/*** Author: jyh* Date: 2020/8/27 22:31* Content:電腦產(chǎn)品類, 保證對象的實例只有一個,減少系統(tǒng)資源的消耗,* spring IOC思想 就是運用了這樣的設(shè)計模式,和原型模式來管理bean實例* 餓漢模式* 餓漢,見名直意,就是類一開始就存在* 1.構(gòu)造方法私有化* 2.創(chuàng)建靜態(tài)類實例,在類被加載的時候就創(chuàng)建* 3.增加一個靜態(tài)方法,返回類實例給調(diào)用者*/ public class Computer {private String CPU;private String memory;private String disk;private String monitor;private static Computer computer=new Computer();//將構(gòu)造方法私有,通過類內(nèi)部返回一個類實例對象private Computer() {}public static Computer getInstants(){return computer;}} package cn.hhw.designModel.factory.single;/*** Author: jyh* Date: 2020/8/27 22:31* Content:電腦產(chǎn)品類, 保證對象的實例只有一個,減少系統(tǒng)資源的消耗,* spring IOC思想 就是運用了這樣的設(shè)計模式,和原型模式來管理bean實例* * 懶漢模式 不提前創(chuàng)建類實例,當(dāng)有調(diào)用者需要使用的時候,再創(chuàng)建* 1.構(gòu)造方法私有化* 2.將對象實例 加 修飾volatile 保證在多線程下數(shù)據(jù)可見性的安全性,對象的實例永遠只有一個* 3.增加一個靜態(tài)方法,返回類實例給調(diào)用者* 4.將方法加同步鎖,DCL 雙重檢查,防止多線程下產(chǎn)生的線程安全問題*/ public class Computer2 {private String CPU;private String memory;private String disk;private String monitor;//讓對象在多線程中可見性,禁止指令重排序private static volatile Computer2 computer;//將構(gòu)造方法私有,通過類內(nèi)部返回一個類實例對象private Computer2() {}//DCL 雙重檢查public static Computer2 getInstants(){if(computer == null){synchronized(Computer2.class) {if(computer == null) {return new Computer2();}}}return computer;}}結(jié)語:餓漢模式比較簡單,沒有線程安全問題。但懶漢模式存在線程安全問題,當(dāng)同一時間多個線程去進入getInstant方法時,可能會創(chuàng)建多個類實例,所以我們需要加鎖,而當(dāng)我們加了synchoronized 同步鎖之后,雖然不會再出現(xiàn)這樣的問題,但是鎖的粗度太大了,以后每個線程進這個方法都要阻塞等待,其實我們只需要保證前幾次的線程進入方法時,不出現(xiàn)問題,當(dāng)類還沒完成創(chuàng)建的時候,同時有兩個線程進入非空校驗,之后有一個線程獲得鎖,創(chuàng)建出實例,這個時候另外一個線程也拿到鎖,但當(dāng)它拿到鎖之后,會再次進行非空判斷,發(fā)現(xiàn)對象已經(jīng)被創(chuàng)建過了,便會直接類實例對象,而后面再來的線程根本就不會進入鎖,所以用一種巧妙DCL的方式,解決了多線程下的安全問題
3.2、工廠模式
1、 實現(xiàn)創(chuàng)建者和調(diào)用者的分離,用工廠方法代替原有的new2、將對象的創(chuàng)建統(tǒng)一管理和控制,從而讓調(diào)用者和我們的實現(xiàn)類解耦3.2.1、簡單工廠模式
- 用于生產(chǎn)同一等級結(jié)構(gòu)內(nèi)的任意產(chǎn)品 package cn.hhw.designModel.factory.simple;/*** Author: jyh* Date: 2020/8/27 20:48* Content:定義一個車的接口,用來規(guī)范*/ 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{@Overridepublic 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{@Overridepublic void getCarName() {System.out.println("大眾車");} } package cn.hhw.designModel.factory.simple;/*** Author: jyh* Date: 2020/8/27 20:54* Content:* 將對象的創(chuàng)建,交給工廠類來創(chuàng)建,統(tǒng)一管理同一類實例* 缺點,當(dāng)我們需要添加 新的車時,還是需要增加方法,修改原有代碼 違背了開閉原則*/ 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對象的方式,而是通過外部的車工廠類去創(chuàng)建不同車的類,但是,當(dāng)我們要增加新的車時,必須要在車工廠* 類里添加方法,修改了原有的類和代碼, 這樣的方式,違背了我們設(shè)計模式的開閉原則,可以擴展,不可以修改*/ 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();} }結(jié)語: 簡單工廠模式,可以代替用戶直接new對象的方式,而是通過外部的車工廠類統(tǒng)一去創(chuàng)建不同車的類實例,但是,當(dāng)我們要增加新的車時,必須要在車工廠
類里添加方法,修改了原有的類和代碼, 這樣的方式,違背了我們設(shè)計模式的開閉原則,可以擴展,不可以修改
3.2.1、工廠方法模式
用來生產(chǎn)同一等級結(jié)構(gòu)中的固定類型產(chǎn)品
/*** Author: jyh* Date: 2020/8/27 20:48* Content:定義一個車的接口,用來規(guī)范*/ public interface Car {void getCarName(); } public class WuLingCar implements Car {@Overridepublic void getCarName() {System.out.println("五菱宏光");} } public class DazhongCar implements Car {@Overridepublic void getCarName() {System.out.println("大眾車");} } /*** Author: jyh* Date: 2020/8/27 21:02* Content: 車工廠接口,用戶可以根據(jù)不同分類的車,去構(gòu)建自己的對應(yīng)車工場*/ public interface Factory {Car CreateCar(); } /*** Author: jyh* Date: 2020/8/27 21:03* Content:大眾車廠*/ public class DazhongFactory implements Factory {@Overridepublic Car CreateCar() {return new DazhongCar();} } /*** Author: jyh* Date: 2020/8/27 21:20* Content:五菱宏光車廠*/ public class WuLingFactory implements Factory {@Overridepublic Car CreateCar() {return new WuLingCar();} } /*** Author: jyh* Date: 2020/8/27 21:05* Content:用戶可以選擇不同的車工場,去獲得資金想要的車。* 1.車工廠接口,2.不同車的工廠實現(xiàn) 3.車的工廠。4.不同車的實現(xiàn)* 用戶需要什么車,便去獲取什么車工廠。這樣實現(xiàn)了,在不修改源代碼的情況下,動態(tài)擴展*/ 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();} }結(jié)語:我們對車工廠也提取了一個接口,這樣實現(xiàn)了再增加新的車的時候,不需要修改原有類,只需要動態(tài)的增加對應(yīng)的車和車工廠即可
符合開閉原則,解決了簡單工廠的問題,但實際觀察下來,代碼復(fù)雜度太高了,類一直在增加,簡單工廠雖然某種程度上不符合設(shè)計原則,但實際使用卻是最多的
3.3、抽象工廠模式
圍繞一個超級工廠,創(chuàng)建其他工廠,又稱為其他工廠的工廠
/*** Author: jyh* Date: 2020/8/27 21:10* Content:手機接口*/ public interface Phone {//開機void start();//關(guān)機void shutdown();//發(fā)短信void sedMes();//打電話void call(); } /*** Author: jyh* Date: 2020/8/27 21:15* Content:路由器接口*/ public interface Routers {//開機void start();//關(guān)機void shutdown();//開始wifivoid Wifi(); } /*** Author: jyh* Date: 2020/8/27 21:12* Content:華為手機*/ public class HuaWeiPhone implements Phone {@Overridepublic void start() {System.out.println("華為手機開機");}@Overridepublic void shutdown() {System.out.println("華為手機關(guān)機");}@Overridepublic void sedMes() {System.out.println("華為手機發(fā)短信");}@Overridepublic void call() {System.out.println("華為手機打電話");} } /*** Author: jyh* Date: 2020/8/27 21:13* Content:小米手機*/ public class XiaoMiPhone implements Phone {@Overridepublic void start() {System.out.println("小米手機開機");}@Overridepublic void shutdown() {System.out.println("小米手機關(guān)機");}@Overridepublic void sedMes() {System.out.println("小米手機發(fā)短信");}@Overridepublic void call() {System.out.println("小米手機打電話");} } /*** Author: jyh* Date: 2020/8/27 21:23* Content:華為路由器*/ public class HuaweiRouter implements Routers {@Overridepublic void start() {System.out.println("華為路由器開機");}@Overridepublic void shutdown() {System.out.println("華為路由器關(guān)機");}@Overridepublic void Wifi() {System.out.println("華為路由器打開wifi");} } /*** Author: jyh* Date: 2020/8/27 21:23* Content:小米路由器*/ public class XiaoMiRouter implements Routers {@Overridepublic void start() {System.out.println("小米路由器開機");}@Overridepublic void shutdown() {System.out.println("小米路由器關(guān)機");}@Overridepublic void Wifi() {System.out.println("小米路由器打開wifi");} } /*** Author: jyh* Date: 2020/8/27 21:24* Content: 產(chǎn)品工廠接口,只提供生產(chǎn)產(chǎn)品的定義,具體需要生產(chǎn)哪類產(chǎn)品,需要產(chǎn)品廠家自己增加實現(xiàn)*/ public interface ProductFatory {Phone gePhone();Routers getRouters();} /*** Author: jyh* Date: 2020/8/27 21:29* Content: * Content:華為的產(chǎn)品工廠,用來生產(chǎn)華為的產(chǎn)品*/ public class HuaweiFactory implements ProductFatory {@Overridepublic Phone gePhone() {return new HuaWeiPhone();}@Overridepublic Routers getRouters() {return new HuaweiRouter();} } /*** Author: jyh* Date: 2020/8/27 21:29* Content:小米的產(chǎn)品工廠,用來生產(chǎn)小米的產(chǎn)品*/ public class XiaoMiFactory implements ProductFatory {@Overridepublic Phone gePhone() {return new XiaoMiPhone();}@Overridepublic Routers getRouters() {return new XiaoMiRouter();} } /*** Author: jyh* Date: 2020/8/27 21:30* Content:用戶在需要使用哪家產(chǎn)品的時候,只需要創(chuàng)建哪家的廠家即可*/ 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();} }結(jié)語:抽象工廠模式是對應(yīng)產(chǎn)品工廠接口,只提供生產(chǎn)產(chǎn)品的定義,具體需要生產(chǎn)哪類產(chǎn)品,需要產(chǎn)品廠家自己增加實現(xiàn),這樣的的設(shè)計模式,可以擴展出不同的產(chǎn)品族,但不能再增加產(chǎn)品,因為產(chǎn)品接口已經(jīng)定義好了,比如我們可以增加蘋果路由器,蘋果手機,和蘋果工廠,這樣動態(tài)擴展即可,不需要修改源代碼便可以實現(xiàn)
工廠模式應(yīng)用場景:
- JDK的calendar的genInstance方法- jdbc的connection對象獲取- springIOC容器創(chuàng)建管理bean對象- 反射中Class對象的newInstance3.4、建造者模式
3.4.1、指揮者存在內(nèi)部
? 提供了一種創(chuàng)建對象的最佳方式,將一個復(fù)雜的對象創(chuàng)建與它的表示分析,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示
/*** Author: jyh* Date: 2020/8/27 22:55* Content:模擬復(fù)雜類*/ 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;}@Overridepublic 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;//此步為關(guān)鍵,實際復(fù)雜對象的實例化必須要有建造者完成。最終返回public Worker() {this.product = new Product();}//建造步驟1.打地基@Overridevoid executeA() {product.setExecuteA("地基");System.out.println("地基");}//建造步驟2.鋪地板@Overridevoid executeB() {product.setExecuteA("地板");System.out.println("地板");}//建造步驟3.裝家具@Overridevoid executeC() {product.setExecuteA("裝家具");System.out.println("裝家具");}//建造步驟3.貼瓷磚@Overridevoid executeD() {product.setExecuteA("貼瓷磚");System.out.println("貼瓷磚");}@OverrideProduct getProduct() {return product;} } package cn.hhw.designModel.factory.builder.demo2;/*** Author: jyh* Date: 2020/8/27 23:10* Content:指揮者,指揮建造者構(gòu)建復(fù)雜對象,可以控制建造者建造的過程*/ 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:調(diào)用者,需要一個對象實例*/ public class Test {public static void main(String[] args) {//創(chuàng)建指揮者,通過指揮者調(diào)用建造者,生產(chǎn)對象Leader leader = new Leader();Product product = leader.Product(new Worker());System.out.println(product);} }上述事例是Builder常規(guī)用法,在用戶不知道對象的建造過程和細節(jié)的情況下就可以直接完成創(chuàng)建復(fù)雜對象,建造和表示分離,實現(xiàn)解耦,創(chuàng)建步驟分解在不同的方法中,使得創(chuàng)建過程更加清晰,具體的建造者類之間是相互獨立的,有利于系統(tǒng)擴展,增加新的建造者,也不需要修改原有類庫,符合‘開閉原則’
3.4.2、指揮權(quán)交給用戶
package cn.hhw.designModel.factory.builder.demo3;/*** Author: jyh* Date: 2020/8/27 23:15* Content:復(fù)雜產(chǎn)品類*/ public class Hamburger {private String hanbao = "漢堡";private String drink = "飲料";private String chip ="薯條";private String cheese="奶酪";@Overridepublic 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();}@OverrideWaiter executeA(String hanbao) {hanHamburger.setHanbao(hanbao);System.out.println(hanbao);return this;}@OverrideWaiter executeB(String drink) {hanHamburger.setHanbao(drink);System.out.println(drink);return this;}@OverrideWaiter executeC(String chip) {hanHamburger.setHanbao(chip);System.out.println(chip);return this;}@OverrideWaiter executeD(String cheese) {hanHamburger.setHanbao(cheese);System.out.println(cheese);return this;}@OverrideHamburger 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();//鏈?zhǔn)骄幊?/span>// waiter.executeA("雞腿皇堡").executeB("可樂兩杯").executeC("巧克力奶酪");waiter.executeA("雞腿皇堡");waiter.executeB("可樂兩杯");waiter.executeC("巧克力奶酪");//這里要是執(zhí)行D步驟,就是默認值Hamburger gethamburger = waiter.gethamburger();System.out.println(gethamburger);} }結(jié)語:指揮者在建造者模式中有重要的作用,通常是知道建造者如何構(gòu)建產(chǎn)品,并向建造者返回完整的產(chǎn)品,有時是可以簡化的,通常會把指揮的權(quán)利交給用戶,通過靜態(tài)內(nèi)部類的方式實現(xiàn)零件無需裝配構(gòu)造,這種方式更加靈活,也更符合定義,內(nèi)部類有復(fù)雜對象的默認實現(xiàn),使用時可以根據(jù)需求自由更改內(nèi)容,無需改變具體的構(gòu)造方法,就可以生產(chǎn)出不同的復(fù)雜產(chǎn)品 缺點是如果產(chǎn)品內(nèi)部變化復(fù)雜,就需要定義很多具有建造者,導(dǎo)致系統(tǒng)變得很龐大
3.5、原型模式
protoType
對復(fù)雜類的直接克隆引用,減少重新構(gòu)建過程
package cn.hhw.designModel.factory.cloneModel;import java.util.Date;/*** Author: jyh* Date: 2020/8/28 20:45* Content:需要被克隆的類* 1.實現(xiàn)cloneable 表示 這個類可以被克隆* 在不實現(xiàn)Cloneable接口的實例上調(diào)用對象的克隆方法導(dǎo)致拋出異常CloneNotSupportedException 。* 2.重寫父類的object方法*/ public class User implements Cloneable {private int id;private String name;private Date birthday;@Overrideprotected 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;}@Overridepublic 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);} }原型模式就是對一個構(gòu)建好的對象進行直接復(fù)制,然后使用,減少了一些復(fù)雜的構(gòu)建過程,提高了復(fù)用性
4、結(jié)構(gòu)型模式
適配器模式,
將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口,使得原本不兼容不可以在一起工作的類可以在一起工作
package cn.hhw.designModel.factory.adapter;/*** Author: jyh* Date: 2020/8/28 21:25* Content: Target 網(wǎng)線,可以上網(wǎng)*/ public class Intel {public void connectionNetwork(){System.out.println("可以上網(wǎng)啦!!!!(*^▽^*)");} } package cn.hhw.designModel.factory.adapter;/*** Author: jyh* Date: 2020/8/28 21:28* Content:類適配器,繼承網(wǎng)線類,則有網(wǎng)線的上網(wǎng)方法*對象適配器*/ public class Adapter extends Intel {@Overridepublic void connectionNetwork() {super.connectionNetwork();} } package cn.hhw.designModel.factory.adapter;/*** Author: jyh* Date: 2020/8/28 21:24* Content:筆記本電腦,需要連接到網(wǎng)線類,但是接口不同,不能直接使用,需要一個中間適配器類來完成這個動作*/ 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:類適配器,繼承網(wǎng)線類,則有網(wǎng)線的上網(wǎng)方法*對象適配器 對于不同的要求,則使用不同的對象進行處理* 適配器,其實應(yīng)該定義為接口*/ public class Adapter {private Intel intel;public Adapter() {this.intel = new Intel();}public void connectionNetwork() {intel.connectionNetwork();} }結(jié)語:三種角色定義,目標(biāo)接口,用戶所需要連接到的真正目標(biāo)類,可以是具體的實現(xiàn),也可以是抽象類或接口,就好像用戶需要上網(wǎng),這個目標(biāo)就是網(wǎng)線類
需要適配的類,這里對應(yīng)的就是電腦,電腦需要適配,那電腦就是需要被適配的類
適配器:通過包裝一個需要適配的對象,吧源接口轉(zhuǎn)換成目標(biāo)對象
一個對象適配器可以把多個不同的適配者配到同一個目標(biāo)
橋接模式,裝飾模式,組合模式,外觀模式,享元模式,代理模式
5、行為型模式
模板方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態(tài)模式、策略模式、職責(zé)鏈模式、訪問者模式
總結(jié)
以上是生活随笔為你收集整理的java设计模式 23种设计模式和思想的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oculus Home启动不了 We'r
- 下一篇: 3D结构光(链接地址提供源码和文献)