Comprendre le modèle composite en comparant le code JavaScript et Java

introduction

Les détails et autres modèles seront écrits dans ** Comprendre les modèles de conception en comparant les implémentations en JavaScript et Java **. J'ai écrit un exemple de JavaScript en regardant Java. Nous ne tirons pas parti des différences de fonctionnalités telles que le type de classe / type de prototype, la force typée et les modificateurs d'accès. Notez s'il vous plaît.

Motif composite

Il existe un "répertoire" dans le système de fichiers de l'ordinateur Il y a d'autres répertoires et fichiers dans le répertoire Les répertoires créent de telles structures "imbriquées", des structures récursives

qiita1.PNG qiita2.PNG

Traitez les répertoires et les fichiers ensemble comme des entrées de répertoire Il peut être pratique de traiter le contenant et son contenu comme du même type

Un modèle qui assimile le contenu au conteneur et crée une structure récursive est appelé le modèle composite. composite signifie «mélange» et «composite»

Exemple d'implémentation en Java

Un programme qui représente schématiquement des fichiers et des répertoires

Diagramme de classe

Composite.png

code

Main.java


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();

            System.out.println("");
            System.out.println("Making user entries...");
            Directory yuki = new Directory("yuki");
            Directory hanako = new Directory("hanako");
            Directory tomura = new Directory("tomura");
            usrdir.add(yuki);
            usrdir.add(hanako);
            usrdir.add(tomura);
            yuki.add(new File("diary.html", 100));
            yuki.add(new File("Composite.java", 200));
            hanako.add(new File("memo.tex", 300));
            tomura.add(new File("game.doc", 400));
            tomura.add(new File("junk.mail", 500));
            rootdir.printList();
        } catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}

Entry.java


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() {
        printList("");
    }
    protected abstract void printList(String prefix);
    public String toString() {
        return getName() + " (" + getSize() + ")";
    }
}

Directory.java


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

public class Directory extends Entry {
    private String name;
    private ArrayList<Entry> directory = new ArrayList<Entry>();
    
    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);
        }
    }
}

File.java


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);
    }
}

FileTreatmentException.java


public class FileTreatmentException extends RuntimeException {
    public FileTreatmentException() {

    }
    public FileTreatmentException(String msg) {
        super(msg);
    }
}

Exemple d'implémentation en JavaScript

code

index.html


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Composite</title>
</head>
<body>
    <script src="Main.js"></script>
    <script src="Directory.js"></script>
    <script src="File.js"></script>
</body>
</html>

Main.js


MAIN = {};

MAIN.init = function() {
    console.log("Making root entries...");
    MAIN.rootdir = new Directory("root");
    MAIN.bindir = new Directory("bin");
    MAIN.tmpdir = new Directory("tmp");
    MAIN.usrdir = new Directory("usr");
    MAIN.rootdir.add(MAIN.bindir);
    MAIN.rootdir.add(MAIN.tmpdir);
    MAIN.rootdir.add(MAIN.usrdir);
    MAIN.bindir.add(new File("vi", 10000));
    MAIN.bindir.add(new File("latex", 20000));
    MAIN.rootdir.printList();

    console.log("");
    console.log("Making user entries...");
    MAIN.yuki = new Directory("yuki");
    MAIN.hanako = new Directory("hanako");
    MAIN.tomura = new Directory("tomura");
    MAIN.usrdir.add(MAIN.yuki);
    MAIN.usrdir.add(MAIN.hanako);
    MAIN.usrdir.add(MAIN.tomura);
    MAIN.yuki.add(new File("diary.html", 100));
    MAIN.yuki.add(new File("Composite.java", 200));
    MAIN.hanako.add(new File("memo.tex", 300));
    MAIN.tomura.add(new File("game.doc", 400));
    MAIN.tomura.add(new File("junk.mail", 500));
    MAIN.rootdir.printList();
};

window.addEventListener("load", MAIN.init);

Directory.js


var Directory = function(name) {
    this.name = name;
    this.directory = [];
};

Directory.prototype = {
    constructor: Directory,

    getName: function() {
        return this.name;
    },
    getSize: function() {
        var size = 0;
        for (var i = 0, max = this.directory.length; i < max; i++) {
            size += this.directory[i].getSize();
        }
        return size;
    },
    add(entry) {
        this.directory.push(entry);
        return this;
    },
    printList: function(prefix) {
        if (arguments.length === 0) {
            console.log("/" + this.getName() + " (" + this.getSize() + ")");
            for (var i = 0, max = this.directory.length; i < max; i++) {
                this.directory[i].printList(this.getName());
            }
        } else {
            console.log(prefix + "/" + this.getName() + " (" + this.getSize() + ")");
            for (var i = 0, max = this.directory.length; i < max; i++) {
                this.directory[i].printList(prefix + "/" + this.getName());
            }
        }
    }
}

File.js


var File = function(name, size) {
    this.name = name;
    this.size = size;
};

File.prototype = {
    constructor: File,

    getName: function() {
        return this.name;
    },
    getSize: function() {
        return this.size;
    },

    printList(prefix) {
        console.log(prefix + "/" + this.getName() + " (" + this.getSize() + ")");
    }
};

Caractères dans le motif composite

** Rôle de Leaf **

Un rôle qui représente le "contenu" Vous ne pouvez rien mettre d'autre dans ce rôle Exemple de programme ⇒ Fichier (classe)

** Le rôle du composite **

Rôle représentant "conteneur" Vous pouvez mettre un rôle Feuille ou un rôle Composite Exemple de programme ⇒ Répertoire (classe)

** Rôle du composant **

Un rôle pour assimiler le rôle Leaf au rôle Composite Le rôle Component est exprimé sous la forme d'une superclasse commune au rôle Leaf et au rôle Composite. Exemple de programme ⇒ Entrée (classe abstraite)

** Le rôle du client **

Utilisateurs du motif composite Exemple de programme ⇒ Principal (classe)

Diagramme de classe de modèle composite

test.png

Besoin d'un motif composite

Sample.java


// Directory
public int getSize() {
  int size = 0;
  Iterator it = directory.iterator();
  while (it.hasNext()) {
    Entry entry = (Entry)it.next();
    size += entry.getSize();
  }
  return size;
}

// File
public int getSize() {
  return size;
}

Dans les deux cas, vous pouvez obtenir la taille avec la même méthode getSize. C'est une manifestation de la caractéristique du modèle composite, «considérant le contenant et le contenu comme la même chose».

Vous pouvez appeler récursivement l'arborescence pour obtenir la taille

qiita3.PNG

Les structures de données généralement structurées en arborescence correspondent au modèle composite

Lors de l'utilisation du motif composite

Un motif composite, etc. est utilisé dans le programme de test

Vous pouvez utiliser le modèle composite lorsque vous souhaitez utiliser ces trois tests comme tests d'entrée.

Modèles associés

référence

[Introduction aux modèles de conception appris dans le langage Java augmenté et révisé](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5 % 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030)

Recommended Posts

Comprendre le modèle composite en comparant le code JavaScript et Java
Comprendre le modèle de stratégie en comparant le code JavaScript et Java
Comprendre le modèle Decorator en comparant le code JavaScript et Java
Comprendre le modèle d'état en comparant le code JavaScript et Java
Comprendre les modèles de conception en comparant les implémentations en JavaScript et Java [mis à jour de temps en temps]
Essayer d'implémenter et de comprendre les arborescences de segments étape par étape (python)
Compilation et exécution Java comprises par CLI
Lisez le fichier en spécifiant le code de caractère.
Comprendre l'arbre de décision et classer les documents
Apprenez le modèle de conception "Composite" avec Python