设计模式之组合模式

文章目录

  • 组合模式
  • 组合模式类
    • 模式类结构图
    • 模式的结构说明
  • 组合模式分类
    • 安全组合模式
    • 透明组合模式
  • Demo
    • 透明模式
    • 安全模式
  • Example
  • 组合模式的应用
  • 组合模式的优缺点
    • 优点:
    • 缺点:

组合模式

组合模式:Composite, 将对象组合成树形结构以表示“部分-整体”的层次机构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

简而言之组合模式

  • 组合模式主要是为了解决树形结构枝节点与叶节点的使用一致性问题。
  • 组合模式分为安全组合模式与透明组合模式。

组合模式类

模式类结构图

设计模式之组合模式_第1张图片

模式的结构说明

模式结构的角色类:

  • Component: 抽象构件,抽象类或接口,定义叶子节点与枝节点共同的方法。
  • Composite: 枝节点,用来维护子节点对象集合。
  • leaf: 叶子节点,末端节点。

组合模式分类

安全组合模式

安全组合模式:Component构件中定义所有除了对于子节点组合关系维护的方法以外的方法。

缺点:

此时由于枝节点中自身维护子节点集合的方法,从而在使用组合模式是需要区分枝节点与叶子节点。

透明组合模式

透明组合模式:Component构件中定义所有方法,特别是对于子节点组合关系维护的方法。

缺点:

与安全模式相反的的是,叶子节点中也继承了子节点关系维护的方法,当叶子节点这些方法被调用时,就会出现错误。

Demo

透明模式

TranslateComponent.java

package com.frank.designMode.CompositeMode.demo.translateDemo;

/**
 * @Description: 透明模式- 定义公共方法与属性, 此组件可以为接口或抽象类
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public abstract class TranslateComponent {

    protected  String name;

    public TranslateComponent(String name){
        this.name = name;
    }

    public abstract  boolean add(TranslateComponent component) throws Exception;
    public abstract  boolean reomve(TranslateComponent component) throws Exception;
    public abstract  void display(int depth);


}

TranslateComposite.java

package com.frank.designMode.CompositeMode.demo.translateDemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Description: 透明模式- 中间组件,含有子节点。
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class TranslateComposite extends TranslateComponent {

    private List<TranslateComponent>  childrenList = new ArrayList<>();

    public TranslateComposite(String name) {
        super(name);
    }

    @Override
    public boolean add(TranslateComponent component) throws Exception {
        return childrenList.add(component);
    }

    @Override
    public boolean reomve(TranslateComponent component) throws Exception {
        return childrenList.remove(component);
    }

    @Override
    public void display(int depth) {

        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.name));
        for (TranslateComponent child:childrenList) {

            child.display(depth+2);
        }

    }
}


Leaf.java

package com.frank.designMode.CompositeMode.demo.translateDemo;

import java.util.Collections;

/**
 * @Description: 叶子节点,终端节点
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class Leaf extends TranslateComponent {

    String resultMsg = "Throw Exception which can't support this method.";


    public Leaf(String name) {
        super(name);
    }

    @Override
    public boolean add(TranslateComponent component) throws Exception{
        // 叶子节点不能增加子节点,抛出异常。
        throw new RuntimeException(resultMsg);
    }

    @Override
    public boolean reomve(TranslateComponent component) throws Exception{
        // 叶子节点不能增加子节点,抛出异常。
        throw new RuntimeException(resultMsg);
    }

    @Override
    public void display(int depth) {
        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.name));
    }
}

Client.java

package com.frank.designMode.CompositeMode.demo.translateDemo;

public class Client {

    public static void main(String[] args) {

        // 透明模式
        try {
            TranslateComponent root = new TranslateComposite("root");
            Leaf leve1_leaf_A = new Leaf("leve1-leaf_A");
            Leaf leve1_leaf_B = new Leaf("leve1-leaf_B");
            root.add(leve1_leaf_A);
            root.add(leve1_leaf_B);
            TranslateComponent leve1_A = new TranslateComposite("leve1-A");
            Leaf leve1_A_leaf_A = new Leaf("leve1-A-leaf_A");
            Leaf leve1_A_leaf_B = new Leaf("leve1-A-leaf_B");
            leve1_A.add(leve1_A_leaf_A);
            leve1_A.add(leve1_A_leaf_B);
            root.add(leve1_A);
            TranslateComponent leve1_B = new TranslateComposite("leve1-B");
            Leaf leve1_B_leaf_A = new Leaf("leve1-B-leaf_A");
            Leaf leve1_B_leaf_B = new Leaf("leve1-B-leaf_B");
            leve1_B.add(leve1_B_leaf_A);
            leve1_B.add(leve1_B_leaf_B);
            root.add(leve1_B);

            root.display(1);
            System.out.println("=================remove TranslateComposite==================");
            root.reomve(leve1_A);
            root.display(1);

        } catch (Exception e) {
            e.printStackTrace();
        }

        //安全模式


    }
}


安全模式

SafeComponent.java

package com.frank.designMode.CompositeMode.demo.safeDemo;

/**
 * @Description: 安全模式- 定义公共方法与属性, 此组件可以为接口或抽象类
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public  abstract class SafeComponent {

    protected  String name;

    public SafeComponent(String name){
        this.name = name;
    }

    public abstract  void display(int depth);
}

SafeComposite.java

package com.frank.designMode.CompositeMode.demo.safeDemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Description: 透明模式- 中间组件,含有子节点。
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class SafeComposite extends SafeComponent {

    private List<SafeComponent>  childrenList = new ArrayList<>();

    public SafeComposite(String name) {
        super(name);
    }

    public boolean add(SafeComponent component) throws Exception {
        return childrenList.add(component);
    }

    public boolean reomve(SafeComponent component) throws Exception {
        return childrenList.remove(component);
    }

    @Override
    public void display(int depth) {

        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.name));
        for (SafeComponent child:childrenList) {

            child.display(depth+2);
        }

    }
}


SafeLeaf.java

package com.frank.designMode.CompositeMode.demo.safeDemo;

import java.util.Collections;

/**
 * @Description: 叶子节点,终端节点
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class SafeLeaf extends SafeComponent {

    String resultMsg = "Throw Exception which can't support this method.";


    public SafeLeaf(String name) {
        super(name);
    }


    @Override
    public void display(int depth) {
        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.name));
    }
}

Client.java

package com.frank.designMode.CompositeMode.demo.translateDemo;

public class Client {

    public static void main(String[] args) {

        // 透明模式
        try {
            TranslateComponent root = new TranslateComposite("root");
            Leaf leve1_leaf_A = new Leaf("leve1-leaf_A");
            Leaf leve1_leaf_B = new Leaf("leve1-leaf_B");
            root.add(leve1_leaf_A);
            root.add(leve1_leaf_B);
            TranslateComponent leve1_A = new TranslateComposite("leve1-A");
            Leaf leve1_A_leaf_A = new Leaf("leve1-A-leaf_A");
            Leaf leve1_A_leaf_B = new Leaf("leve1-A-leaf_B");
            leve1_A.add(leve1_A_leaf_A);
            leve1_A.add(leve1_A_leaf_B);
            root.add(leve1_A);
            TranslateComponent leve1_B = new TranslateComposite("leve1-B");
            Leaf leve1_B_leaf_A = new Leaf("leve1-B-leaf_A");
            Leaf leve1_B_leaf_B = new Leaf("leve1-B-leaf_B");
            leve1_B.add(leve1_B_leaf_A);
            leve1_B.add(leve1_B_leaf_B);
            root.add(leve1_B);

            root.display(1);
            System.out.println("=================remove TranslateComposite==================");
            root.reomve(leve1_A);
            root.display(1);

        } catch (Exception e) {
            e.printStackTrace();
        }

        //安全模式


    }
}


Example

FolderComponent.java

package com.frank.designMode.CompositeMode.demo.example;

/**
 * @Description: 文件对象与文件夹对象抽象类
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public abstract class FolderComponent {

    protected   String fileName;

    public FolderComponent(String fileName){
        this.fileName = fileName;
    }


    public abstract void addFile(FolderComponent component) throws  Exception;
    public abstract void removeFile(FolderComponent component) throws  Exception;
    public abstract  void display(int depth);
}

ConcreteFolder.java

package com.frank.designMode.CompositeMode.demo.example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Description: 文件夹对象抽象类
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class ConcreteFolder extends FolderComponent{

    private List<FolderComponent> childrenList = new ArrayList<>();

    public ConcreteFolder(String fileName) {
        super(fileName);
    }

    @Override
    public void addFile(FolderComponent component) throws Exception {
        childrenList.add(component);
    }

    @Override
    public void removeFile(FolderComponent component) throws Exception {
        childrenList.remove(component);
    }

    @Override
    public void display(int depth) {
        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.fileName));
        for (FolderComponent child:childrenList) {

            child.display(depth+2);
        }

    }
}

FileLeaf.java

package com.frank.designMode.CompositeMode.demo.example;

import java.util.Collections;

/**
 * @Description: 叶子节点,具体文件类
 * @Author: Frank.Liu
 * @Date:25/05/2020
 */
public class FileLeaf  extends FolderComponent{

    String resultMsg = "Throw Exception which can't support this method.";
    public FileLeaf(String fileName) {
        super(fileName);
    }

    @Override
    public void addFile(FolderComponent component) throws Exception {

    }

    @Override
    public void removeFile(FolderComponent component) throws Exception {

    }

    @Override
    public void display(int depth) {
        System.out.println(String.format( String.join("-", Collections.nCopies(depth, ""))+this.fileName));
    }
}

Client.java

package com.frank.designMode.CompositeMode.demo.example;

public class Client {

    public static void main(String[] args) {

        // 透明模式
        try {
            FolderComponent rootFolder = new ConcreteFolder("FolderRoot");
            FolderComponent fileA = new FileLeaf("fileA");
            FolderComponent fileB = new FileLeaf("fileB");
            rootFolder.addFile(fileA);
            rootFolder.addFile(fileB);
            FolderComponent folderA = new ConcreteFolder("FolderA");
            FolderComponent fileC = new FileLeaf("fileC");
            FolderComponent fileD = new FileLeaf("fileD");
            folderA.addFile(fileC);
            folderA.addFile(fileD);
            rootFolder.addFile(folderA);

            FolderComponent folderB = new ConcreteFolder("FolderB");
            FolderComponent fileE = new FileLeaf("fileE");
            FolderComponent fileF = new FileLeaf("fileF");
            folderB.addFile(fileE);
            folderB.addFile(fileF);
            rootFolder.addFile(folderB);

            rootFolder.display(1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //安全模式


    }
}

组合模式的应用

  • 在具有整体和部分的层次结构中,希望通忽略整体与部分的差异从而一致性的对待。
  • 功能中需要树形结构。
  • 解耦叶子对象和容器对象,而且它们的类型不固定,动态增加新类型。

组合模式的优缺点

优点:

  • 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
  • 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

缺点:

  • 使得设计更加复杂,客户端需要花更多时间理清类之间的层次关系。
  • 在增加新构件时很难对容器中的构件类型进行限制。

你可能感兴趣的:(设计模式,Java)