# Design Pattern ## 什麼是Design Pattern? @StanShih 在程式設計中,經常遇到相同的設計問題,許多設計可以解決這些重複出現的問題,但隨著時間推進,某些設計因為更加的靈活,而優於了其他的設計。而這些設計被整理歸類,進而發展出了Design Pattern。Design Pattern即是針對這些反覆出現的問題而提出的解決方案。 Design Pattern一書中介紹了 23 種模式,依照不同的狀況,使用不同的模式,解決不同的問題。而所謂的Design Pattern並非一組source code,他為一個概念。 ```markmap # Design Pattern ## 創建型模式 --對象創建和使用分離 ### 單例模式 Singleton ### 工廠模式 Factory ### 抽象工廠模式 Abstract Factory ### 建造者模式 Builder ### 原型模式 Prototype ## 結構型模式 -- 類or對象組合成更大的結構 ### 適配器模式 Adapter ### 代理模式 Proxy #### 靜態代理 #### 動態代理 ### 裝飾模式 Decorator ### 組合模式 Composite ### 外觀模式 Facade Pattern ### 橋接模式 Bridge Patern ### 享元模式 Flyweight Pattern ## 行為型模式 -- 類or對象之間的動作 ### 觀察者模式 Observer ### 策略模式 Strategy ### 迭代器模式 Iterator ### 命令模式 Command ### 模板方法模式 Template ### 狀態模式 State ### 職責鏈模式 Chain of Responsibility ### 中介者模式 Mediator ### 備忘錄模式 Memento ### 解釋器模式 Interpreter ### 訪問者模式 Visitor ``` https://zhuanlan.zhihu.com/p/380570323 ### 為什麼要使用Design Pattern? Design Pattern為一些專家,歷經無數的錯誤及試驗而得到的結果。 我們舉一個例子,小學我們都學過如何把1加到100。我們可以怎麼做?? 方法一:土法煉鋼直接從頭加 > 1+2+3...+100 方法二:已知的數學公式 > n(n+1)/2 很明顯,方法二已經有一個“公式”可以幫助我們快速的解決問題,不但簡化過程也節省了時間。 但只是節省過程與時間嗎?? 我們把問題再做延伸,假設今天需要更改成相加1000個數字,那我們該怎麼辦?? 方法一依舊要從1加到1000,但方法二只需要把n改成1000。 這樣的差距,就很像我們在程式開發過程中,突然有需要做變更或是新增需求,如果有使用合適的design pattern,便可輕鬆解決很複雜的問題。 所以使用Design Pattern目的,除了建立良好的軟體系統外,不管在未來維護程式或是新增需求,都可以大大節省我們的時間及精力。 引用 https://ithelp.ithome.com.tw/articles/10234830 ## 建立型模式 在軟體工程中,建立型模式是處理對象建立的設計模式,試圖根據實際情況使用合適的方式建立對象,因為基本的對象建立方式可能會導致設計上的問題,或增加設計的複雜度。建立型模式的關注點是如何建立對象,其核心思想是要把對象的建立和使用相分離。 建立型模式由兩個主導思想構成。一是將系統使用的具體類封裝起來,二是隱藏這些具體類別的實例建立的方式。 建立型模式又分為對象建立型模式和類建立型模式。對象建立型模式處理對象的建立,類建立型模式處理類的建立。詳細地說,對象建立型模式把對象建立的一部分推遲到另一個對象中,而類建立型模式將它對象的建立推遲到子類中。 使用模式我們希望達到不自己創建物件的效果(在程式碼中不使用new),把創建的過程封裝起來,從而達到單一實例、提升效能、容易擴充···等等的好處 建立型設計模式的一些例子如下: [工廠方法模式](#工廠方法模式-Factory-Method-Pattern) [單例模式](#單例模式(Singleton-Pattern)) [建構者模式](#建構者模式-Builder-Pattern) ## 結構型模式 跟將物件組合成更大的結構有關的模式,歸類為結構型模式 1.轉接器模式 ( Adapter Pattern ) 將一個類別的介面轉換為客戶希望的另一個介面。使得原本由於介面不相容而不能一起工作的那些類別可以一起工作。 雖然本來的物件、方法不適合現在使用,但希望建立一個可以重用這個類別的機制,讓這個類別跟其他類別一起共同工作。  2.橋接模式 ( Bridge Patern ) 將抽象的部分和他的實現部分分離,使他們都可以獨立的變化。 代替繼承的關係從而使用組合的關係,像是在借用別人所實踐出的方法,使這兩者可以各自獨立實現其獨立的變化。  範例: 一個頁面需要呈現各種不同商品,但是頁面上又需要有不同的頁面,例如只呈現簡單資訊的頁面和詳細資訊的頁面,要把這些不同的資訊串接起來··· 定義頁面的Super Class ```java public abstract class View { Resources resources; public void setResources(Resources resources){ this.resources = resources; } // 定義畫面如何擺放 public abstract void show(); } ``` 定義來源的介面 ```java public interface Resources { public void photo(); public void snippet(); public void describe(); } ``` 書本: public class Book implements Resources { @Override public void photo() { System.out.println("書本的照片"); } @Override public void snippet() { System.out.println("書本的簡短說明"); } @Override public void describe() { System.out.println("書本詳細說明"); } } 包包: ```java public class Bag implements Resources { @Override public void photo() { System.out.println("包包的照片"); } @Override public void snippet() { System.out.println("包包的簡短說明"); } @Override public void describe() { System.out.println("包包詳細說明"); } ``` 小資訊的頁面根所有資訊的頁面 小資訊 ```java public class FewView extends View{ @Override public void show() { resources.photo(); resources.snippet(); } } ``` 所有資訊 ```java public class FullView extends View { @Override public void show() { resources.photo(); resources.describe(); } } ``` 測試一下 ``` public class Test { @org.junit.jupiter.api.Test public void test(){ FewView fewView = new FewView(); System.out.println("---- 簡單包包說明 ----"); fewView.setResources(new Bag()); fewView.show(); System.out.println("---- 簡單書本說明 ----"); fewView.setResources(new Book()); fewView.show(); FullView fullView = new FullView(); System.out.println("---- 詳細包包說明 ----"); fullView.setResources(new Bag()); fullView.show(); System.out.println("---- 詳細書本說明 ----"); fullView.setResources(new Book()); fullView.show(); } } ``` > 結果: > ---- 簡單包包說明 ---- > 包包的照片 > 包包的簡短說明 > ---- 簡單書本說明 ---- > 書本的照片 > 書本的簡短說明 > ---- 詳細包包說明 ---- > 包包的照片 > 包包詳細說明 > ---- 詳細書本說明 ---- > 書本的照片 > 書本詳細說明 3.組合模式 ( Composite Pattern ) 將物件組合成樹形結構以表示「部分-整體」結構,組合模式使得用戶對單個物件和組合物件的使用具有一致性。 適合用來表示一種不論是個體,或是組合起來一個部分(整體),都需要做一些相同的運算(工作)的模式,例如公司(團體)的組織。 動態的添加職責像是在事後(程式碼中)才定義各個在基本之外需要具備的其他功能(在android中有關於view的實踐是使用這種方式)。  4.裝飾模式 ( Decorator Pattern ) 動態的給一個物件添加一下額外的職責。就增加功能性來說,裝飾模式比產生子類別更加靈活。 組合模式是一種樹狀的結構,而裝飾模式像是將一個Component經過各個Decorator包裹起來,核心是Component、而Decorator像是糖果或是巧克力一般一層一層包裹的結構。  5.外觀模式 ( Facade Pattern ) 為子系統中的一組介面提供一致的介面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。 常常會是重構過程中第一步驟所做的模式。為子系統引入了這個單一的屏障,讓程式碼更容易被理解而且依賴關係較小。  6.享元模式 ( Flyweight Pattern ) 為運用共同的技術有效地支援大量細粒度的物件。 最早期的應用有各個字元(文字)的顯示···等等,為了避免佔用資源過多,透過相同物件共享的機制增加效能  7.代理模式 ( Proxy Pattern ) 為其他物件提供一種代理以控制對這個物件的存取。 單一另一個物件的代理人。  ## 行為型模式 行為型模式(Behavioral Patterns)是一組設計模式,用於描述物件之間的職責分配和協作,以及物件如何互動和傳遞訊息。這些模式關注的是物件之間的通訊、職責分配和控制流程。行為型模式有助於實現更靈活、可維護和可擴展的程式碼。 一些例子如下: [觀察者模式](#觀察者模式--Observer-Pattern-) ## 併發型模式 解決多執行緒和併發程式設計中的各種問題和挑戰。這些模式旨在幫助開發人員編寫線程安全的程式碼,避免競態條件、死鎖、活鎖等併發問題。 一些例子如下: 讀寫鎖 ## 單例模式(Singleton Pattern) 主要目標是確保一個類別只有一個實例,並提供全域訪問點,以便在整個應用程式中可以方便地訪問該實例。單例模式通常在需要控制某個資源的訪問時使用。 * **私有建構函數**:單例類別的建構函數必須是私有的,以防止外部程式碼通過建構函數創建多個實例。 * **靜態實例變數**:單例類別通常包含一個私有靜態成員變數,用於存儲該類別的唯一實例。 * **公共靜態方法**:單例類別提供一個公共的靜態方法,允許外部程式碼獲取該類別的唯一實例。這個方法通常稱為 getInstance()。 * **延遲初始化**:單例模式可以採用延遲初始化的方式,在第一次訪問時創建實例,而不是在類別加載時就創建實例。 ```public class Singleton { private static volatile Singleton instance = null; private Singleton() { // 初始化操作 } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` ```public class Main { public static void main(String[] args) { // 獲取單例實例 Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); // 判斷是否為同一實例 if (singleton1 == singleton2) { System.out.println("singleton1 和 singleton2 是同一個實例"); } } } ``` ### 單例模式(Singleton Pattern)通常在以下情況下非常有用: 1. **資源共享**:當應用程式需要共享資源,如資料庫連接池、執行緒池、日誌記錄器或配置管理器時,可以使用單例模式確保僅有一個實例來管理這些資源,以避免資源競爭和浪費。 2. **全域對象**:當需要在整個應用程式中共享某個對象的狀態或功能時,可以使用單例模式來建立該對象的唯一實例。例如,遊戲中的全域狀態管理器或應用程式的全域設定。 3. **節省資源**:某些對象的建立和初始化可能需要大量的時間和資源,因此希望盡量減少建立這些對象的次數。使用單例模式可以在需要時才建立實例,而不是在應用程式啟動時就建立。 4. **限制實例數量**:在某些情況下,需要限制一個類別的實例數量,例如,執行緒池可能需要限制可以同時執行的執行緒數量,可以使用單例模式來管理這些執行緒。 5. **日誌記錄器**:在應用程式中記錄日誌是一個常見需求。使用單例模式可以確保只有一個日誌記錄器實例,以便在不同部分的程式碼中記錄一致的日誌訊息。 6. **快取管理**:如果需要實現一個快取,可以使用單例模式來管理快取對象,以確保只有一個快取實例用於儲存和檢索資料。 7. **控制訪問點**:單例模式可以用於建立一個全域訪問點,以便在整個應用程式中訪問特定功能或狀態。這有助於提供統一的介面,而無需直接建立類別的實例。 ## 工廠方法模式 (Factory Method Pattern) 工廠方法模式( Factory Method ),定義一個用於建立物品的介面,讓子類決定實體化哪一個類別。工廠方法使一個類別的實例化延遲到其子類別。 -- 大話設計模式 p.105 工廠方法模式類別之間的關係像是下面這樣 * Creator:創造者經由FactoryMethod創造產品 * Product:被創造的產品類別  EX: 假設我們去速食店買無鹽的薯條 首先我們要有一個商品和工廠的介面... ```java public interface Product { //敘述自己是什麼商品 public void describe(); } public interface Factory { //工廠返回商品 public Product getProduct(); } ``` ```java //薯條 public class FrenchFries implements Product{ //預設有鹽巴的 String state = "有鹽巴"; //預設的建構 protected FrenchFries(){} //帶入狀態的建構 protected FrenchFries(String state){ this.state = state; } @Override public void describe() { System.out.println("我是"+ state +"薯條"); } } ``` ```java //薯條工廠 public class FrenchFriesFactory implements Factory { //返回一般的薯條 @Override public Product getProduct() { return new FrenchFries(); } //返回我們想要的狀態的薯條.. public Product getProduct(String state) { return new FrenchFries(state); } } ``` ```java //嘗試調用薯條工廠做出顧客想要的薯條,成功做出顧客想要的薯條 Factory friesFac = new FrenchFriesFactory(); Product fries = friesFac.getProduct(); Product myfries = ((FrenchFriesFactory) friesFac).getProduct("無鹽的"); fries.describe();//我是有鹽巴薯條 myfries.describe();//我是無鹽的薯條 ``` 藉由工廠模式, 我們可以在調用的時候才決定我們想要的物品狀態, 在商品中加入大中小包等等的參數, 我們可以決定要哪種份量的商品, 甚至可以決定我們要幾根薯條, 用方法或是各種方式把物件的創造包裝起來, 工廠模式的實現方式很多, 但工廠有個重點會返回我們想要的商品, 掌握這個重點碰到類似的創建模式相信都可以很快掌握喔! ## 建構者模式 (Builder Pattern) @Vincentl92 ### Builder模式的定義 以下是維基百科上建構者模式的定義 ```! The Builder is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the Builder design pattern is to separate the construction of a complex object from its representation. It is one of the Gang of Four design patterns. ``` 簡單的翻譯一下, 建構者模式是設計來提供一個有彈性解決方案,用OOP的方式來解決一個不同(複雜)物件的創造。目的是為了要分離一個複雜物品的建造和表示建造的方式。 一個物品在建造完成的過程中,需要組成需要設定過多的元件,或裝配過程是有順序的,可以在一一設定完所需要的元件後再產生我們所需要的物件。主要的角色有建造者、指揮者和產品,指揮者控制建造的過程,並且可以用來區隔用戶和建造過程的關聯性。  ### 建構者模式的優點 1. 更好的可讀性: 建造者模式可以提高代碼的可讀性,因為它使代碼更具表達性。通過連續的方法調用,可以清晰地看到對象的構建過程。 1. 參數可選性: 建造者模式允許您設置對象的某些參數,而忽略其他參數。這樣可以輕鬆地創建不同配置的對象,而無需使用多個重載構造函數。 1. 避免重複代碼: 建造者模式可以避免在代碼中重複相似的創建邏輯,因為創建過程被封裝在建造者中,可以在多個地方重複使用。 1. 更好的可擴展性: 如果需要添加新的屬性或配置選項,只需擴展建造者而不需要修改客戶端代碼,這提高了代碼的可維護性。 1. 創建不可變對象: 建造者模式通常用於創建不可變對象,這些對象的狀態在創建後不能被修改,這有助於確保對象的一致性和安全性。 1. 具有複雜構建邏輯: 當創建對象的構建邏輯比較複雜,或者涉及多個步驟時,建造者模式特別有用。它可以將這些步驟分解為簡單的方法調用。 1. 改進代碼可測試性: 建造者模式使測試更容易,因為您可以創建偽造的建造者來創建測試對象,並設置所需的屬性。 ### 範例 建構MacBook Pro 是一個複雜的過程,元件非常多,有各種規格可以客製化,也有分高規格跟低規格版,我們試著用builder pattern實現建造的過程。 ```Java public class MacbookPro { private Processor processor; private Memory memory; private Storage storage; private Graphics graphics; private Keyboard keyboard; MacbookPro(){} public void setProcessor(Processor processor) { this.processor = processor; } public void setMemory(Memory memory) { this.memory = memory; } public void setStorage(Storage storage) { this.storage = storage; } public void setGraphics(Graphics graphics) { this.graphics = graphics; } public void setKeyboard(Keyboard keyboard) { this.keyboard = keyboard; } public Processor getProcessor() { return processor; } public Memory getMemory() { return memory; } public Storage getStorage() { return storage; } public Graphics getGraphics() { return graphics; } public Keyboard getKeyboard() { return keyboard; } @Override public String toString() { return "{ Macbook : " + "\n" + "Processor : " + this.getProcessor().name + "\n" + "Memory size : " + this.getMemory().size + "GB" + "\n" + "Graphics : " + this.getGraphics().name + "\n" + "Storage size : " + this.getStorage().size + "GB" +"\n" + "Keyboard language : "+ this.getKeyboard().language + " }"; } public static class Processor{ String name; Processor(String name){ this.name = name; } } public static class Memory{ int size; Memory(int size){ this.size = size; } } public static class Graphics{ String name; Graphics(String name){ this.name = name; } } public static class Storage{ int size; Storage(int size){ this.size = size; } } public static class Keyboard{ String language; Keyboard(String language){ this.language = language; } } } ``` MacbookBuilder介面類別 ```Java Public abstract class MacbookProBuilder { protected MacbookPro macbookPro; MacbookProBuilder(){ macbookPro = new MacbookPro(); } abstract MacbookProBuilder buildCPU(MacbookPro.Processor processor); abstract MacbookProBuilder buildMemory(MacbookPro.Memory size); abstract MacbookProBuilder buildGraphics(MacbookPro.Graphics name); abstract MacbookProBuilder buildStorage(MacbookPro.Storage size); abstract MacbookProBuilder buildKeyboard(MacbookPro.Keyboard language); MacbookPro build(){ return macbookPro; } } ``` 實際的Builder ```Java Public class MacbookPro_2018 extends MacbookProBuilder { @Override MacbookPro build() { return super.build(); } MacbookPro_2018() { super(); } @Override MacbookProBuilder buildCPU(MacbookPro.Processor processor) { this.macbookPro.setProcessor(processor); return this; } @Override MacbookProBuilder buildMemory(MacbookPro.Memory size) { this.macbookPro.setMemory(size); return this; } @Override MacbookProBuilder buildGraphics(MacbookPro.Graphics name) { this.macbookPro.setGraphics(name); return this; } @Override MacbookProBuilder buildStorage(MacbookPro.Storage size) { this.macbookPro.setStorage(size); return this; } @Override MacbookProBuilder buildKeyboard(MacbookPro.Keyboard language) { this.macbookPro.setKeyboard(language); return this; } } ``` 賣macbook的經銷商,只有兩種固定規格的macbook ```Java public class MacBookSeller { private MacbookProBuilder macbookProBuilder; MacBookSeller(MacbookProBuilder macbookProBuilder){ this.macbookProBuilder = macbookProBuilder; } public MacbookPro lowSpec(){ return macbookProBuilder .buildCPU(new MacbookPro.Processor("2.2GHz 6 核心第八代 Intel Core i7 處理器")) .buildMemory(new MacbookPro.Memory(16)) .buildGraphics(new MacbookPro.Graphics("Radeon Pro 555X 配備 4GB GDDR5 記憶體")) .buildStorage(new MacbookPro.Storage(256)) .buildKeyboard(new MacbookPro.Keyboard("中文注音")) .build(); } public MacbookPro highSpec(){ return macbookProBuilder .buildCPU(new MacbookPro.Processor("2.6GHz 6 核心第八代 Intel Core i7 處理器")) .buildMemory(new MacbookPro.Memory(16)) .buildGraphics(new MacbookPro.Graphics("Radeon Pro 560X 配備 4GB GDDR5 記憶體")) .buildStorage(new MacbookPro.Storage(512)) .buildKeyboard(new MacbookPro.Keyboard("中文注音")) .build(); } } ``` 測試 ```java public class Test { @org.junit.jupiter.api.Test public void test(){ MacbookPro_2018 macbookPro_2018 = new MacbookPro_2018(); MacBookSeller macBookSeller = new MacBookSeller(macbookPro_2018); //經銷商的固定規格 MacbookPro myMacbook= macBookSeller.lowSpec(); System.out.println(myMacbook.toString()); //想要夢想中的macbook pro需要自己訂製 MacbookPro dreamMacbook = macbookPro_2018 .buildCPU(new MacbookPro.Processor("2.9GHz 6 核心第八代 Intel Core i9 處理器")) .buildMemory(new MacbookPro.Memory(32)) .buildStorage(new MacbookPro.Storage(4096)) .buildKeyboard(new MacbookPro.Keyboard("英文")) .buildGraphics(new MacbookPro.Graphics("Radeon Pro 560X 配備 4GB GDDR5 記憶體")) .build(); System.out.println(dreamMacbook.toString()); } } ``` 結果 ``` { Macbook : Processor : 2.2GHz 6 核心第八代 Intel Core i7 處理器 Memory size : 16GB Graphics : Radeon Pro 555X 配備 4GB GDDR5 記憶體 Storage size : 256GB Keyboard language : 中文注音 } { Macbook : Processor : 2.9GHz 6 核心第八代 Intel Core i9 處理器 Memory size : 32GB Graphics : Radeon Pro 560X 配備 4GB GDDR5 記憶體 Storage size : 4096GB Keyboard language : 英文 } ``` ## 觀察者模式 ( Observer Pattern ) Chris ### 定義: 觀察者模式是一種一對多的依賴關係,當物件的狀態改變,所有依賴於它的物件都會得到通知並被自動更新。 ### 例子: 假設有學生訂閱了廣播,每一段時間會換節目。 觀察者和被觀察者的介面 ```java public interface IObserverable { public void add(IObserver observer); public void remove(IObserver observer); public void notifyObservers(); } public interface IObserver { public void update(); } ``` 實體的廣播 ```java import java.util.ArrayList; import java.util.List; public class PodcastA implements IObserverable { List<IObserver> list = new ArrayList<>(); //節目名稱 String name = "英文廣播"; @Override public void add(IObserver observer) { list.add(observer); } @Override public void remove(IObserver observer) { list.remove(observer); } public String getName() { return this.name; } @Override public void notifyObservers() { for (IObserver o: list) { o.update(); } } } ``` 實體的學生 ```java public class Student implements IObserver { IObserverable observerable; public Student(IObserverable observerable){ this.observerable = observerable; } @Override public void update() { System.out.println("聽了" + observerable.getName()); } } ``` 測試 ```java public class Test { @org.junit.jupiter.api.Test public void test(){ IObserverable podcast = new PodcastA(); IObserver student = new Student(podcast); podcast.add(student); //預設節目是英文廣播 podcast.notifyObservers(); //節目變為今年流行歌 ((PodcastA) podcast).name = "今年流行歌"; podcast.notifyObservers(); } } ``` 結果 ``` 聽了英文廣播 聽了今年流行歌 ``` ## Adapter Adapter is a structural design pattern that allows objects with incompatible interfaces to collaborate.  ``` package com.journaldev.design.adapter; public class Volt { private int volts; public Volt(int v){ this.volts=v; } public int getVolts() { return volts; } public void setVolts(int volts) { this.volts = volts; } } package com.journaldev.design.adapter; public class Socket { public Volt getVolt(){ return new Volt(120); } } ``` shen @Danny ## 外觀模式 ( Facade Pattern ) 是一種封裝的應用,將各種系統和類別等等雜亂或是困難的函數式封裝起來,成為一個容易使用和理解的介面,Client端只要調用此一介面就可以實踐想要的功能,而不用理會背後的邏輯。  ``` public class SubClassOne { public void MethodOne(){ System.out.println(1); } } public class SubClassTwo { public void MethodTwo(){ System.out.println(2); } } public class SubClassThree { public void MethodThree(){ System.out.println(3); } } public class ClassOne { public void MethodFour(){ System.out.println(4); } } ``` Facade Class ``` public class Facade { private SubClassOne one; private SubClassTwo two; private SubClassThree three; private ClassOne four; public Facade(){ one = new SubClassOne(); two = new SubClassTwo(); three = new SubClassThree(); four = new ClassOne(); } public void MethodA(){ four.MethodFour(); one.MethodOne(); } public void MethodB(){ two.MethodTwo(); three.MethodThree(); } } ``` Test ``` public class Test { @org.junit.jupiter.api.Test public void test(){ Facade facade = new Facade(); System.out.println("MethodA : "); facade.MethodA(); System.out.println("MethodB : "); facade.MethodB(); } } MethodA : 4 1 MethodB : 2 3 ``` ## Iterator pattern @D5k22DL6TsqCosjRchaFYg ENSEAN ### 目的 了解 forEach() 的來由。 ### 說明 簡單來說,實作任意資料結構的 forEach(),最常見的莫過於 Array、List 等,其他像是 Linked List、Stack、Queue、Tree 等也是可實作的資料結構,在模式內負責儲存的物件稱作 Aggregate。 ```java // 迭代器接口 interface Iterator { boolean hasNext(); Object next(); } // 具體迭代器 class ConcreteIterator implements Iterator { private int index = 0; private String[] elements; public ConcreteIterator(String[] elements) { this.elements = elements; } public boolean hasNext() { return index < elements.length; } public Object next() { return elements[index++]; } } // 聚合物件接口 interface Aggregate { Iterator createIterator(); } // 具體聚合物件 class ConcreteAggregate implements Aggregate { private String[] elements; public ConcreteAggregate(String[] elements) { this.elements = elements; } public Iterator createIterator() { return new ConcreteIterator(elements); } } // 使用範例 public class Main { public static void main(String[] args) { String[] elements = {"A", "B", "C", "D", "E"}; Aggregate aggregate = new ConcreteAggregate(elements); Iterator iterator = aggregate.createIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } } ``` 總結 Iterator 模式可說是歷史的軌跡,1994 年的時候,forEach() 的概念尚未成為許多程式語言的內建語法,因此需要特地開一個模式教導他人如何實作。時光飛逝,forEach() 的概念已經變成許多語言的內建語法 ## 額外討論 ### PureMVC https://puremvc.org/  ### 推薦 https://refactoring.guru/design-patterns https://www.tenlong.com.tw/products/9789572054116
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up