每天一個設計模式之組合模式

godbmw發表於2018-12-15

作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用javascriptpython兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :)

原文地址是:《每天一個設計模式之組合模式》

歡迎關注個人技術部落格:godbmw.com。每週 1 篇原創技術分享!開源教程(webpack、設計模式)、面試刷題(偏前端)、知識整理(每週零碎),歡迎長期關注!

如果您也想進行知識整理 + 搭建功能完善/設計簡約/快速啟動的個人部落格,請直接戳theme-bmw

0. 專案地址

1. 什麼是“組合模式”?

組合模式,將物件組合成樹形結構以表示“部分-整體”的層次結構。

  1. 用小的子物件構造更大的父物件,而這些子物件也由更小的子物件構成
  2. 單個物件和組合物件對於使用者暴露的介面具有一致性,而同種介面不同表現形式亦體現了多型性

2. 應用場景

組合模式可以在需要針對“樹形結構”進行操作的應用中使用,例如掃描資料夾、渲染網站導航結構等等。

3. 程式碼實現

這裡用程式碼模擬檔案掃描功能,封裝了FileFolder兩個類。在組合模式下,使用者可以向Folder類巢狀File或者Folder來模擬真實的“檔案目錄”的樹結構。

同時,兩個類都對外提供了scan介面,File下的scan是掃描檔案,Folder下的scan是呼叫子資料夾和子檔案的scan方法。整個過程採用的是深度優先

3.1 python3 實現

class File:  # 檔案類
    def __init__(self, name):
        self.name = name

    def add(self):
        raise NotImplementedError()

    def scan(self):
        print('掃描檔案:' + self.name)


class Folder:  # 資料夾類
    def __init__(self, name):
        self.name = name
        self.files = []

    def add(self, file):
        self.files.append(file)

    def scan(self):
        print('掃描資料夾: ' + self.name)
        for item in self.files:
            item.scan()


if __name__ == '__main__':

    home = Folder("使用者根目錄")

    folder1 = Folder("第一個資料夾")
    folder2 = Folder("第二個資料夾")

    file1 = File("1號檔案")
    file2 = File("2號檔案")
    file3 = File("3號檔案")

    # 將檔案新增到對應資料夾中
    folder1.add(file1)

    folder2.add(file2)
    folder2.add(file3)

    # 將資料夾新增到更高階的目錄資料夾中
    home.add(folder1)
    home.add(folder2)

    # 掃描目錄資料夾
    home.scan()

複製程式碼

執行$ python main.py, 最終輸出結果是:

掃描資料夾: 使用者根目錄
掃描資料夾: 第一個資料夾
掃描檔案:1號檔案
掃描資料夾: 第二個資料夾
掃描檔案:2號檔案
掃描檔案:3號檔案
複製程式碼

3.2 ES6 實現

// 檔案類
class File {
  constructor(name) {
    this.name = name || "File";
  }

  add() {
    throw new Error("資料夾下面不能新增檔案");
  }

  scan() {
    console.log("掃描檔案: " + this.name);
  }
}

// 資料夾類
class Folder {
  constructor(name) {
    this.name = name || "Folder";
    this.files = [];
  }

  add(file) {
    this.files.push(file);
  }

  scan() {
    console.log("掃描資料夾: " + this.name);
    for (let file of this.files) {
      file.scan();
    }
  }
}

let home = new Folder("使用者根目錄");

let folder1 = new Folder("第一個資料夾"),
  folder2 = new Folder("第二個資料夾");

let file1 = new File("1號檔案"),
  file2 = new File("2號檔案"),
  file3 = new File("3號檔案");

// 將檔案新增到對應資料夾中
folder1.add(file1);

folder2.add(file2);
folder2.add(file3);

// 將資料夾新增到更高階的目錄資料夾中
home.add(folder1);
home.add(folder2);

// 掃描目錄資料夾
home.scan();
複製程式碼

執行$ node main.js,最終輸出結果是:

掃描資料夾: 使用者根目錄
掃描資料夾: 第一個資料夾
掃描檔案: 1號檔案
掃描資料夾: 第二個資料夾
掃描檔案: 2號檔案
掃描檔案: 3號檔案
複製程式碼

4. 參考

  • 《JavaScript 設計模式和開發實踐》

相關文章