1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「容器」と「中身」を同一視するということについて【コンポジットパターン】

Posted at
最終更新日: 20230305

はじめに

ライトな感じでコンポジットパターンに触れてみようってテーマの記事です

コンポジットパターンってようは、ツリー型データ構造作りたいから同一視して再帰処理するってことだと思うんですけど
まず頭に入れるべきことは「同一視」かなって個人的には思ってます

ツリー型データ構造が必要ならライブラリ使えば良いで終わりな気がするけど
同一視って設計概念は頭の片隅に置いとけば役に立つ日が来る予感!

何が実現できる?

「容器」と「中身」を同一視するということは
「容器」を「中身」として見ることができるので

下記のような「容器」に「容器」を格納する入れ子構造が実現可能

* ディレクトリ
    * ディレクトリA
        * ファイルA
    * ディレクトリB
        * ファイルB
    * ファイルC

クラス図

引用: Java言語で学ぶデザインパターン入門 結城 浩

スクリーンショット 2024-03-05 101940.jpg

ソース

使用する言語はJavaです

引用: Java言語で学ぶデザインパターン入門 結城 浩

Entryクラス

この柚象クラスを親(スーパークラス)に子(サブクラス)を作ることで
Entry型として同一視することができる

public abstract class Entry {
    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws FileTreatmentException {
        throw new FileTreatmentException();
    }
    
    public void printList() {  // Fileクラスの実装例で解説すると System.out.println(prefix + "/" + this) の prefixが "" ってこと
        printList("");
    }
    protected abstract void printList(String prefix);

    public String toString() {
        return getName() + " (" + getSize() + ")";
    }
}

Fileクラス

Entryのサブクラス

public class File extends Entry {  
    private String name;
    private int size;
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        return size;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
    }
}

Directoryクラス

重要なのはadd関数かな
DirectoryとFileはEntryクラスのサブクラスだから両方Entry型として扱える
だからDirectoryという「容器」に「容器と中身」を入れることができる

printListgetSizeも同一視してるから再帰的に処理できるねってことです

import java.util.ArrayList;
import java.util.Iterator;

public class Directory extends Entry {
    private String name;
    private ArrayList directory = new ArrayList(); 
    public Directory(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        int size = 0;
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            size += entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry) {
        directory.add(entry);
        return this;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            entry.printList(prefix + "/" + name);
        }
    }
}

使用例

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Making root entries...");
            Directory rootdir = new Directory("root");
            Directory bindir = new Directory("bin");
            Directory tmpdir = new Directory("tmp");
            Directory usrdir = new Directory("usr");
            rootdir.add(bindir);
            rootdir.add(tmpdir);
            rootdir.add(usrdir);
            bindir.add(new File("vi", 10000));
            bindir.add(new File("latex", 20000));
            rootdir.printList();
            }catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}

実行結果

Making root entries...
/root (30000)
/root/bin (30000)
/root/bin/vi (10000)
/root/bin/latex (20000)
/root/tmp (0)
/root/usr (0)

まとめ

めちゃ端折ると
「容器」と「中身」に共通のスーパークラスを持って
「容器」にaddクラスを実装して容器と中身入れられるね再帰的でもあるねってだけかな

おわりに

こういう設計概念を学べるのがデザインパターン学習の醍醐味ですよね
現実的にはデザインパターンが言ってる実装したいならライブラリ使えばいいと思うですけど
設計概念は雰囲気で頭に取り入れとけば役に立つ日が来ると思います!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?