0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Gang of Four】Composite

Last updated at Posted at 2019-03-18

#Composite
目次
**クラスを木構造で組み立てる。**とあるように、compositeとleafと呼ばれるオブジェクトで構成するパターンのようです。

##目的
部分―全体階層を表現するために、オブジェクトを木構造に組み立てる。Composite パターンにより、クライアントは、個々のオブジェクトとオブジェクトを合成したものを一様に扱うことができるようになる。

##構成要素
・Component 根、節、葉の抽象クラス
・Leaf 葉
・Composite 根または節
・Client 使用者

##実装
木構造と聞くとディレクトリツリーが思い浮かびますね。
ということでディレクトリツリーを管理、出力できるプログラムを実装します。

directoryがcompositeでfileがleafですね。

###Component 根、節、葉の抽象クラス
directoryとfileのインターフェース

Element.kt
package composite

interface Element {
    enum class ElementType(val type: String) {
        DIRECTORY("Direcotry"),
        FILE("File")
    }

    fun getType(): ElementType
    fun getName(): String
}

###Composite 根または節
directory抽象クラス

elementListを持たせ、自分の配下にいるElementを管理できるようにします。

AbstractDirectory.kt
package composite

abstract class AbstractDirectory: Element {
    var elementList: MutableList<Element> = mutableListOf()

    abstract fun addElement(element: Element)
}

directory具象クラス

Directory.kt
package composite

class Directory(private val name: String): AbstractDirectory() {

    override fun getType(): Element.ElementType {
        return Element.ElementType.DIRECTORY
    }

    override fun addElement(element: Element) {
        elementList.add(element)
    }

    override fun getName(): String {
        return name
    }
}

###Leaf 葉
file具象クラス

File.kt
package composite

class File(private val name: String): Element {

    override fun getType(): Element.ElementType {
        return Element.ElementType.FILE
    }

    override fun getName(): String {
        return name
    }
}

###Client 使用者
ディレクトリツリーを管理する人

DirectoryManager.kt
package composite

class DirectoryManager {
    init {
        // ルートフォルダ
        val rootDirectory = Directory("/")
        rootDirectory.addElement(File("sample.config"))
        rootDirectory.addElement(File("gof.env"))

        // iOSアプリ用フォルダ
        val iosDirectory = Directory("iOS")

        val iosAppDirectory = Directory("GofiOSApp")
        iosAppDirectory.addElement(File("xcode.project"))

        val iosAppSourceDirectory = Directory("Source")
        iosAppSourceDirectory.addElement(File("hoge.swift"))
        iosAppSourceDirectory.addElement(File("fuga.swift"))

        iosDirectory.addElement(iosAppDirectory)
        iosAppDirectory.addElement(iosAppSourceDirectory)
        rootDirectory.addElement(iosDirectory)

        // Androidアプリ用フォルダ
        val androidDirectory = Directory("AndroidOS")

        val androidAppDirectory = Directory("GofAndroidApp")
        androidAppDirectory.addElement(File("AndroidManifest.xml"))

        val androidAppSourceDirectory = Directory("Source")
        androidAppSourceDirectory.addElement(File("moge.kt"))
        androidAppSourceDirectory.addElement(File("unbaba.kt"))

        androidDirectory.addElement(androidAppDirectory)
        androidAppDirectory.addElement(androidAppSourceDirectory)
        rootDirectory.addElement(androidDirectory)

        show(rootDirectory, 0)
    }

    private fun show(element: Element, indent: Int) {

        if (element is Directory) {
            println("${"----".repeat(indent)}【${element.getType().type}】${element.getName()}")
            element.elementList.forEach {
                show(it, indent + 1)
            }
        } else {
            println("${"----".repeat(indent)}【${element.getType().type}】${element.getName()}")
        }
    }
}

以上でcompositeパターンを用いたディレクトリツリーの完成です。

###出力結果

[output]
【Direcotry】/
----【File】sample.config
----【File】gof.env
----【Direcotry】iOS
--------【Direcotry】GofiOSApp
------------【File】xcode.project
------------【Direcotry】Source
----------------【File】hoge.swift
----------------【File】fuga.swift
----【Direcotry】AndroidOS
--------【Direcotry】GofAndroidApp
------------【File】AndroidManifest.xml
------------【Direcotry】Source
----------------【File】moge.kt
----------------【File】unbaba.kt

/iOS/GofIosApp/Sourceフォルダを同じ階層へ複製したくなった場合、iosAppDirectory.addElement(iosAppSourceDirectory)を追加します。

[output]
【Direcotry】/
----【File】sample.config
----【File】gof.env
----【Direcotry】iOS
--------【Direcotry】GofiOSApp
------------【File】xcode.project
------------【Direcotry】Source
----------------【File】hoge.swift
----------------【File】fuga.swift
------------【Direcotry】Source
----------------【File】hoge.swift
----------------【File】fuga.swift
略

ディレクトリを自由自在に操れてます。
※kotlinは文字列操作なんかも簡潔に書けていいですね。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?