4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[iOS/Swift] アプリ開発の実務的アプローチで学ぶデザインパターン ~Composite~

Last updated at Posted at 2020-01-14

この記事シリーズは、iOS/Swiftエンジニアである執筆者個人が、
ごく普通のiOSアプリ開発でよくある状況
Swiftのコアライブラリやフレームワークで使われているパターン
着目してデザインパターンを学び直してみた記録です。

関連記事一覧
[iOS/Swift] アプリ開発の実務的アプローチで学ぶデザインパターン

Compositeパターン概要

  • ディレクトリとファイルのような、ツリー構造を扱うためのパターンです。
  • ディレクトリとファイルのように、「名前」などの同じプロパティや、「削除」などの同じ操作を持つ場合、ディレクトリ(容器)とファイル(中身)を同じように扱うことができます。
  • すなわち、検索や削除などを再帰的に行うことができます。
  • GoFのデザインパターンでは構造に関するパターンに分類されます。

使い所

  • そのものズバリ、ツリー構造を扱う場合には、Compositeパターンを思い浮かべると設計に掛かる時間を短縮できる可能性が高いです。
  • UIViewのView Hierarchyもツリー構造であり、Compositeパターンが使われています。

view_hierarchy.gif
引用:Cocoa Design Patterns (Retired Document)

サンプルコード

Swiftバージョンは 5.1 です。

protocol DirectoryEntry {
    var name: String { get }
    func remove()
}

final class File: DirectoryEntry {
    let name: String
    
    init(name: String) {
        self.name = name
    }
    
    func remove() {
        print("\(name)を削除しました")
    }
}

final class Directory: DirectoryEntry {
    let name: String
    private var entryList = [DirectoryEntry]()

    init(name: String) {
        self.name = name
    }
    
    func add(entry: DirectoryEntry) {
        entryList.append(entry)
    }

    func remove() {
        for entry in entryList {
            entry.remove()
        }
        print("\(name)を削除しました")
    }
}

// Usage
let dir1 = Directory(name: "dir1")
let file1 = File(name: "file1")
dir1.add(entry: file1)
// dir1
//   ∟file1

let dir2 = Directory(name: "dir2")
let file2 = File(name: "file2")
let file3 = File(name: "file3")
dir2.add(entry: file2)
dir2.add(entry: file3)
// dir2
//   ∟file2
//   ∟file3

dir1.add(entry: dir2)
// dir1
//   ∟file1
//   ∟dir2
//     ∟file2
//     ∟file3

let file4 = File(name: "file4")
dir1.add(entry: file4)
// dir1
//   ∟file1
//   ∟dir2
//     ∟file2
//     ∟file3
//   ∟file4

dir1.remove()
// "file1を削除しました"
// "file2を削除しました"
// "file3を削除しました"
// "dir2を削除しました"
// "file4を削除しました"
// "dir1を削除しました"
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?