摘要:維基百科抽象工廠的例子構(gòu)建模式當(dāng)構(gòu)建一個復(fù)雜對象時,就可以使用建造者模式。在中,類中的方法就是適配器模式的例子,把一個數(shù)組轉(zhuǎn)換為一個集合。這種設(shè)計模式的好處是方便添加一種車巴士,只需要繼承類。
寫在前面
評判一個程序員是否優(yōu)秀,就是 show me the code。優(yōu)秀的代碼可讀性強(qiáng),高內(nèi)聚低耦合,可擴(kuò)展。想要寫優(yōu)秀的代碼,做個優(yōu)秀的程序員,就需要多看看大牛寫的開源框架,吸取其中的精華,多學(xué)學(xué)設(shè)計模式,除此之外,沒有任何其他捷徑。
設(shè)計模式主要分為創(chuàng)建型模式、結(jié)構(gòu)型模式、行為型模式三種類型。
工廠方法(Factory method pattern)定義一個創(chuàng)建對象的接口,讓實現(xiàn)這個接口的類來決定實例化哪個類。工廠方法讓類的實例化推遲到子類中進(jìn)行,它屬于創(chuàng)建型模式。
工廠對象通常包含一個或多個方法,用來創(chuàng)建這個工廠所能創(chuàng)建的各種類型的對象。這些方法可能接收參數(shù),用來指定對象創(chuàng)建的方式,最后返回創(chuàng)建的對象。
工廠通常是一個用來創(chuàng)建其他對象的對象。工廠是構(gòu)造方法的抽象,用來實現(xiàn)不同的分配方案。
維基百科工廠方法的例子
// 定義了 Button 如何創(chuàng)建 public interface Button{} // 實現(xiàn)了 WinButton public class WinButton implements Button{} // 實現(xiàn)了 MacButton public class MacButton implements Button{} // 創(chuàng)建 Button 的工廠類 public interface ButtonFactory { Button createButton(); } // 真正創(chuàng)建 WinButton 的實現(xiàn)類,實現(xiàn)了 ButtonFactory public class WinButtonFactory implements ButtonFactory { @Override public static Button createButton(){ return new WinButton(); } } // 真正創(chuàng)建 MacButton的實現(xiàn)類,實現(xiàn)了 ButtonFactory public class MacButtonFactory implements ButtonFactory { @Override public static Button createButton(){ return new MacButton(); } }抽象工廠模式(Abstract factory pattern)
將一組具有同一主題的多帶帶的工廠封裝起來。在使用中,使用方需要創(chuàng)建抽象工廠的具體實現(xiàn),然后使用抽象工廠作為接口來創(chuàng)建這一方法的具體對象。它屬于創(chuàng)建型模式。
抽象工廠就好像是對工廠方法的一種擴(kuò)展,有個產(chǎn)品族的概念,也就是一堆產(chǎn)品。上面的工廠方法就一個產(chǎn)品(Button),而下面抽象工廠的例子里有兩個產(chǎn)品(Button和 Border)。
抽象工廠的優(yōu)點:
具體產(chǎn)品從客戶代碼中被分離出來。
容易改變產(chǎn)品的系列。
將一個系列的產(chǎn)品族統(tǒng)一到一起創(chuàng)建。
抽象工廠的缺點:
在產(chǎn)品族中擴(kuò)展新的產(chǎn)品是很困難的,它需要修改抽象工廠的接口。
維基百科抽象工廠的例子
public interface Button {} public interface Border {} public class WinButton implements Button {} public class WinBorder implements Border {} public class MacButton implements Button {} public class MacBorder implements Border {} public interface AbstractFactory { Button createButton(); Border createBorder(); } public class WinFactory { @Override public static Button createButton() { return new WinButton(); } @Override public static Border createBorder() { return new WinBorder(); } } public class MacFactory { @Override public static Button createButton() { return new MacButton(); } @Override public static Border createBorder() { return new MacBorder(); } }構(gòu)建模式(Builder pattern)
當(dāng)構(gòu)建一個復(fù)雜對象時,就可以使用建造者模式。它實際上就是傳入一個參數(shù),然后返回對象本身,方便下一個屬性或者參數(shù)來構(gòu)建。可以按需構(gòu)建對象,可擴(kuò)展性強(qiáng)。它屬于創(chuàng)建型模式。
在 JDK 中,StringBuilder 類的 append() 方法就是一個很好的構(gòu)建模式例子。
// java.lang.StringBuilder @Override public StringBuilder append(CharSequence s) { super.append(s); return this; }原型模式(Prototype pattern)
它的特點在于通過 復(fù)制 一個已經(jīng)存在的實例來返回新的實例,而不是新建實例。被復(fù)制的實例就是我們所稱的原型,這個原型是可定制的。它屬于創(chuàng)建型模式。
原型模式多用于創(chuàng)建復(fù)雜的或者耗時的實例,因為這種情況下,復(fù)制一個已經(jīng)存在的實例使程序運行更高效,它們實際上就是命名不一樣的同類數(shù)據(jù)。
在 JDK 中,Object 類中的 clone() 方法就是典型的原型模式。
//在具體的實現(xiàn)類里可以直接重寫 clone() 方法 protected native Object clone() throws CloneNotSupportedException;單例模式(Singleton pattern)
不管在任何時候,獲取一個對象時只會返回同一個實例。通常我們在都讀取配置文件時,文件里的內(nèi)容是不變的,因此我們就可以使用單例模式來實現(xiàn)。它屬于創(chuàng)建型模式。
單例模式很簡單,只需要三步就完成,下面是 JDK 里的 Runtime 類實現(xiàn)的單例模式。
public class Runtime { // 1.new 一個私有的靜態(tài)的 Runtime 實例 private static Runtime currentRuntime = new Runtime(); // 2.返回當(dāng)前應(yīng)用的 Runtime 實例 public static Runtime getRuntime() { return currentRuntime; } // 3.私有化構(gòu)造方法,不允許在其它類構(gòu)造 Runtime 實例 private Runtime() {} }適配器模式(Adapter pattern)
適配器模式也稱作包裝(wrapper),它屬于結(jié)構(gòu)型模式。
它的作用是把原本兩個不兼容的接口通過一個適配器或者包裝成兼容的接口,然后它們可以一起工作。例如我們的手機(jī)數(shù)據(jù)線,就好比是一個適配器,一端是 USB接口,一端是 Type-C 或者 Lightning 接口,本來它們是不能一起工作的,但我們用這跟數(shù)據(jù)線(適配器)就可以讓它們協(xié)同工作了。
它的優(yōu)點:
1.可以讓任何兩個沒有關(guān)聯(lián)的接口一起工作。
2.提高了接口的復(fù)用。
3.增加了接口的透明度。
4.靈活性好。
它的缺點:
1.過多地使用適配器,會讓系統(tǒng)非常零亂,不易整體進(jìn)行把握。
2.由于 JAVA 只能繼承一個類,所以最多只能適配一個適配者類,而且目標(biāo)類必須是抽象類。
在 JDK 中,Arrays 類中的 asList(T... a) 方法就是適配器模式的例子,把一個數(shù)組轉(zhuǎn)換為一個集合。
public staticList asList(T... a) { return new ArrayList<>(a); }
在 JDK 中,Collections 工具類的 list() 方法把枚舉轉(zhuǎn)集合。
public staticArrayList list(Enumeration e) { ArrayList l = new ArrayList<>(); while (e.hasMoreElements()) l.add(e.nextElement()); return l; }
當(dāng)然,這上面兩個例子是非常簡單的,好像看不出來使用了任何的設(shè)計模式,跟我們平時使用的轉(zhuǎn)換一模一樣。這里只是一個理念的介紹,實際上,在使用中是用一個中間的 Adapter 類來做兼容或者包裝的。
橋接模式(Bridge pattern)將抽象與其實現(xiàn)分離,以便兩者可以獨立變化。它屬于結(jié)構(gòu)型模式。
當(dāng)一個類經(jīng)常變化時,面向?qū)ο缶幊痰奶匦宰兊梅浅S杏茫驗榭梢杂米钌俚年P(guān)于程序的先驗知識來容易地改變程序的代碼。當(dāng)類和它經(jīng)常變化時,橋模式很有用。類本身可以被認(rèn)為是抽象,類可以作為實現(xiàn)來做。橋模式也可以被認(rèn)為是兩層抽象。
它通過提供抽象化和實現(xiàn)化之間的橋接結(jié)構(gòu),來實現(xiàn)二者的解耦。
它的優(yōu)點:
1.抽象和實現(xiàn)分離開。
2.優(yōu)秀的擴(kuò)展能力。
3.實現(xiàn)細(xì)節(jié)對調(diào)用方透明。
它的缺點:
橋接模式的引入會增加系統(tǒng)的理解與設(shè)計難度,由于聚合關(guān)聯(lián)關(guān)系建立在抽象層,需要針對抽象進(jìn)行設(shè)計與編程,加深編程難度。
這是個生產(chǎn)不同車輛和需要不同生產(chǎn)流程的例子。首先,定義一個車輛(Vehicle)的抽象接口,里面有個生產(chǎn)車輛的對應(yīng)流程集合和一個生產(chǎn)的抽象方法。然后是自行車(Bike)和汽車(Car)對抽象接口的實現(xiàn)。然后定義一個生產(chǎn)車輛需要的流程(WorkShop),它有兩個實現(xiàn) ProduceWorkShop 和 TestWorkShop。最后,main 方法的代碼就是對這個橋接模式的使用方式。
這種設(shè)計模式的好處是方便添加一種車巴士(Bus),只需要繼承 Vehicle 類。也非常方便的添加一種生產(chǎn)流程噴漆(PaintWorkShop),只需要繼承 WorkShop 類即可,擴(kuò)展性很高。
//車輛的抽象接口 public abstract class Vehicle { // protected Listworkshops = new ArrayList (); public Vehicle() { super(); } public boolean joinWorkshop(WorkShop workshop) { return workshops.add(workshop); } public abstract void manufacture(); } //自行車的實現(xiàn) public class Bike extends Vehicle { @Override public void manufacture() { System.out.println("Manufactoring Bike..."); workshops.stream().forEach(workshop -> workshop.work(this)); } } //汽車的實現(xiàn) public class Car extends Vehicle { @Override public void manufacture() { System.out.println("Manufactoring Car"); workshops.stream().forEach(workshop -> workshop.work(this)); } } //生產(chǎn)車的抽象接口 public abstract class WorkShop { public abstract void work(Vehicle vehicle); } //制造車的實現(xiàn) public class ProduceWorkShop extends WorkShop { public ProduceWorkShop() { super(); } @Override public void work(Vehicle vehicle) { System.out.print("Producing... "); } } //測試車的實現(xiàn) public class TestWorkShop extends WorkShop { public TestWorkShop() { super(); } @Override public void work(Vehicle vehicle) { System.out.print("Testing... "); } } //使用 public class Main { public static void main(String[] args) { //生產(chǎn)一輛自行車 Vehicle bike = new Bike(); bike.joinWorkshop(new ProduceWorkShop()); bike.manufacture(); //生產(chǎn)一輛汽車 Vehicle car = new Car(); car.joinWorkshop(new ProduceWorkShop()); car.joinWorkshop(new TestWorkShop()); car.manufacture(); } }
最后,單看設(shè)計模式例子是非常簡單的,但有時候?qū)懘a時卻用不上這些設(shè)計模式,這是一種寫代碼思維上的轉(zhuǎn)變。也就是在寫代碼之前,我們需要根據(jù)業(yè)務(wù)場景思考,那種設(shè)計模式適合使用,記住使用設(shè)計模式的最終目的是代碼可讀性強(qiáng),高內(nèi)聚低耦合,可擴(kuò)展。這是一種思維上的轉(zhuǎn)變,多思考在動手,熟能生巧。
PS:
清山綠水始于塵,博學(xué)多識貴于勤。
微信公眾號:「清塵閑聊」。
歡迎一起談天說地,聊代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/74913.html
摘要:提供酒店相關(guān)的接口返回該時間段有效的酒店提供航班相關(guān)的接口返回該時間段有效的航班提供一個旅行對外的接口,一次返回酒店和航班信息調(diào)用旅行外觀模式享元模式享元模式主要用于減少創(chuàng)建對象的數(shù)量,以減少內(nèi)存占用和提高性能。 組合模式(Composite pattern) 組合模式看起來就像對象組的樹形結(jié)構(gòu),一個對象里面包含一個或一組其他的對象。它是屬于結(jié)構(gòu)型模式。例如,一個公司包括很多個部門,每...
摘要:是一款基于的服務(wù)端渲染框架,跟的異曲同工。該配置項用于定義應(yīng)用客戶端和服務(wù)端的環(huán)境變量。 Vue因其簡單易懂的API、高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng),受到很多前端開發(fā)人員的青睞。國內(nèi)很多公司都在使用vue進(jìn)行項目開發(fā),我們正在使用的簡書,便是基于Vue來構(gòu)建的。 我們知道,SPA前端渲染存在兩大痛點:(1)SEO。搜索引擎爬蟲難以抓取客戶端渲染的頁面meta信息和其他SEO相關(guān)信息,使...
摘要:是一款基于的服務(wù)端渲染框架,跟的異曲同工。該配置項用于定義應(yīng)用客戶端和服務(wù)端的環(huán)境變量。 Vue因其簡單易懂的API、高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng),受到很多前端開發(fā)人員的青睞。國內(nèi)很多公司都在使用vue進(jìn)行項目開發(fā),我們正在使用的簡書,便是基于Vue來構(gòu)建的。 我們知道,SPA前端渲染存在兩大痛點:(1)SEO。搜索引擎爬蟲難以抓取客戶端渲染的頁面meta信息和其他SEO相關(guān)信息,使...
摘要:全書分三大部分共章第章介紹的基礎(chǔ)知識安裝和基本語法第章介紹的基本編程機(jī)器學(xué)習(xí)基礎(chǔ)及中常用的第三方庫函數(shù),并介紹數(shù)據(jù)預(yù)處理的基本方法第章分別介紹常用的機(jī)器學(xué)習(xí)分析算法及深度學(xué)習(xí)等。每章都采用多個經(jīng)典案例圖文并茂地介紹機(jī)器學(xué)習(xí)的原理和實現(xiàn)方法。 最近在學(xué)習(xí)Java和全棧開發(fā),推薦一些有用的書籍 書架主要針對Java后端和全棧開發(fā)用的 書籍介紹 《Spring Boot 2.0企業(yè)級應(yīng)用開發(fā)...
閱讀 2449·2021-10-08 10:17
閱讀 1824·2021-09-06 15:02
閱讀 2539·2019-08-29 17:30
閱讀 2663·2019-08-29 13:24
閱讀 1522·2019-08-29 11:12
閱讀 3337·2019-08-28 17:52
閱讀 666·2019-08-26 11:30
閱讀 3577·2019-08-26 11:01