Java設計モードの組合せモード(Composite Pattern)

10235 ワード

紹介する
コンビネーションモードは構造型設計モードである.一般的には、「部分-全体」の階層関係を表すツリー構造を作成します.このモードはオブジェクトの組合せを用いて実現されるため,継承方式とは異なるため,合成モードとも呼ばれる.定義を見てみましょう
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. オブジェクトをツリー構造に結合して「部分-全体」の階層を表し、ユーザーが単一のオブジェクトと組合せオブジェクトの使用に一貫性を持つようにします.
コンビネーション・モードには、主に3つのロールがあります.
  • Component抽象コンポーネントロール.オブジェクトのフレームワークを定義し、共通のメソッドを実装したり、クラスのプロパティを定義したりすることができます.単一のオブジェクトと組合せオブジェクトが継承されます.
  • Leafリーフセット.樹状構造の葉に相当し、構造の最下層であり、下には他のコンポーネントはない.
  • Component枝組立体.樹状構造の枝分かれノードに相当し、下には他の枝コンポーネントまたは葉コンポーネントがあり、それは容器に相当し、下の各コンポーネントを含み、その下の各コンポーネントの父親である.

  • この3つのキャラクターがあればコンビネーションモードを実現できます.コンビネーションモードの応用は多く、最も一般的なのは私たちのファイルシステムで、1つのフォルダの下に他のフォルダがたくさんあり、多くのファイルがあります.ここのフォルダは私たちの木の枝コンポーネント(容器)に相当し、ファイルは葉コンポーネント(他のコンポーネントを含まない)に相当します.
    コンビネーションモードには、セキュリティモードと透明モードの2つの異なる実装があります.名前から分かるように、セキュリティモードは透明モードよりも安全です.実は安全モードは、木の枝と木の葉のコンポーネントを別々に定義することによって安全性を実現し、透明モードは区別されない.以下、コンビネーションモードについて具体的に説明します.
    注意:透明モードの実装では、ツリーのメソッドが抽象コンポーネントに配置されるため、透明モードの実装の組合せモードは2つのキャラクタしかありません.
    セーフモード
    私たちのファイルシステムを例に挙げると、ここでは両者の抽象コンポーネントが必要です.
    public abstract class FileSystem {
        protected String fileName = "";
        public FileSystem(String fileName) {
            this.fileName = fileName;
        }
    }

    次に、ツリーと木の葉コンポーネント、つまりフォルダとファイルを定義します.
    フォルダ:
    public class Folder extends FileSystem {
        private List fileList = new ArrayList<>();
        public Folder(String fileName) {
            super(fileName);
        }
        //        。
        public void add(FileSystem fileSystem) {
            this.fileList.add(fileSystem);
        }
        //        。
        public void remove(FileSystem fileSystem) {
            this.fileList.remove(fileSystem);
        }
        //         、     。
        public List getChildren() {
            return this.fileList;
        }
        @Override
        public String toString() {
            String name = "    :" + this.fileName + "
    "
    ; for (FileSystem fileSystem : fileList) { name = name + fileSystem; } return name; } }

    ファイル:
    public class File extends FileSystem {
        public File(String fileName) {
            super(fileName);
        }
        @Override
        public String toString() {
            return "   :" + this.fileName + "
    "
    ; } }

    最後に、3つのコンポーネントを定義すると、テストを開始できます.
    public static void main(String[] args) {
        Folder root = new Folder("    ");
        Folder branch = new Folder("    ");
        File leaf = new File("  .jpg");
        root.add(branch);
        branch.add(leaf);
        display(root);
    }
    public static void display(Folder root) {
        for (FileSystem fileSystem : root.getChildren()) {
            System.out.println(fileSystem);
        }
    }

    出力結果:
    フォルダ名:私の画像ファイル名:画像.jpg
    これが安全モード実現の組合せモードであり,枝と木の葉を分離して定義することによってシステムの安全性を保証する.
    透過モード
    透明モードとは、セキュリティモードにおける特定のクラスのメソッドを抽象クラスに入れたものであり、例えばadd()メソッド、remove()メソッド、getChildren()メソッドなどである.変更後のコードを見てみましょう.
    抽象コンポーネント:
    public abstract class FileSystem {
        protected List fileList = new ArrayList<>();
        protected String fileName = "";
        public FileSystem(String fileName) {
            this.fileName = fileName;
        }
        //        。
        public void add(FileSystem fileSystem) {
            this.fileList.add(fileSystem);
        }
        //        。
        public void remove(FileSystem fileSystem) {
            this.fileList.remove(fileSystem);
        }
        //         、     。
        public List getChildren() {
            return this.fileList;
        }
        @Override
        public String toString() {
            String name = "    :" + this.fileName + "
    "
    ; for (FileSystem fileSystem : fileList) { name = name + fileSystem; } return name; } }

    フォルダとファイルは同じです.
    public class File extends FileSystem {
        public File(String fileName) {
            super(fileName);
        }
        //    。
        @Override
        public String toString() {
            String name = "    :" + this.fileName + "
    "
    ; for (FileSystem fileSystem : this.fileList) { name = name + fileSystem; } return name; } }

    最後のテストコードは、セキュリティモードとは少し異なります.
    public static void main(String[] args) {
        File root = new File("    ");
        File branch = new File("    ");
        File leaf = new File("  .jpg");
        root.add(branch);
        branch.add(leaf);
        display(root);
    }
    public static void display(FileSystem root) {
        for (FileSystem fileSystem : root.getChildren()) {
            System.out.println(fileSystem);
        }
    }

    出力結果:
    フォルダ名:私の画像フォルダ名:画像.jpg
    このモードの枝コンポーネントと葉コンポーネントの構造は同じであり,安全モードよりも実装クラスが1つ少ないことがわかる.しかし、葉コンポーネントではこれらの方法は使用できないが、抽象クラスに置くと使用できるという問題が発生する.これは潜在的な危険をもたらす.リーフコンポーネントは、これらの方法で書き換えることができるが、必要はないので、ここでは、組合せモードを実現するためにセキュリティモードを使用することを推奨する.
    まとめ
    コンビネーション・モードは、データベース・システムなどの複雑なオブジェクトを作成する場合に、特にツリー構造のオブジェクトに適しています.メリットは2つあります.
  • 枝組立体でも葉組立体でも、使用者にとって何の違いもなく、上位モジュールは、組合せ対象でも単一対象でも気にする必要はない.
  • 対象を自由に増やすことができる.ファイルシステムのように、フォルダやファイルを追加または削除することは、現在のフォルダにのみ影響を与え、他の部分は正常に動作します.このような開発は開閉の原則に合致し、拡張が容易です.

  • しかしながら、組合せモードにも欠点があり、最大の欠点は、使用時にその実装クラスを直接使用することであり、これは依存逆置原則と衝突する.