文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

一文彻底搞明白组合模式

2024-11-29 23:07

关注

定义

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

在新的分类方式中,组合模式被划分至类之间的交互类别中,其简化的是调用方与具备树结构的一组对象之间的交互,具体通过一致性的行为实现。

模式应用前案例

下面以一个典型的文件和目录为例来进行说明,先来看一下未应用组合模式之前的代码实现。

public class File {//文件结构

    private final String name;

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

    public void display() {
        System.out.println("File: " + this.name);
    }
}

public class Directory {//目录结构

    private String name;
    private final List files;
    private final List directories;

    // 初始化方法
    public Directory(String name){
        this.name = this.name;
        this.files = new ArrayList<>();
        this.directories = new ArrayList<>();
    }

    // 添加子节点
    public void addFile(File file){
        this.files.add(file);
    }

    // 添加子目录
    public void addDirectory(Directory directory) {
        this.directories.add(directory);
    }

    public void display(){
        //System.out.println("Directory:"+this.name);
        for(File file : this.files){
            file.display();
        }

        for (Directory dir : this.directories) {
            dir.display();
        }
    }
}

public class Client {//调用方代码

    public static void main(String[] ars){

        Directory root= new Directory("Root");

        File file1=new File("file1.txt");
        File file2=new File("file2.txt");
        root.addFile(file1);
        root.addFile(file2);
        Directory subDirecory =new Directory ("Subdirectory");

        File file3 = new File("file3.tx");
        File file4 = new File("file4.tx");
        subDirecory.addFile(file3);
        subDirecory.addFile(file4);
        root.addDirectory(subDirecory);
        root.display();
    }
}

我们知道,文件和目录两者是一个大的树结构中的节点。在上面未使用组合模式的代码中,文件和目录都有自己定义的方法。这样在构建一个多层树结构的过程中,复杂度会提升。

结构

组合模式的示例代码如下。

public interface Component {
    void operation();
    void add(Component component);
    void remove(Component component);
    Component Display(int index);
}

public class Leaf implements Component{
    private String name;

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

    @Override
    public void operation() {
        System.out.println("Leaf: " + name + " operation()");
    }

    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException("Leaf cannot have children");
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException("Leaf cannot remove children");
    }

    @Override
    public Component Display(int index) {
        throw new UnsupportedOperationException("Leaf cannot get child");
    }

}

public interface Component {
    void operation();
    void add(Component component);
    void remove(Component component);
    Component Display(int index);
}

public class Client {
    public static void main(String[] args) {
        // 创建叶子节点
        Component leaf1 = new Leaf("LeafA");
        Component leaf2 = new Leaf("LeafB");
        Component leaf3 = new Leaf("LeafC");

        // 创建复合节点
        Component composite = new Composite("CompositeX");
        composite.add(leaf1);
        composite.add(leaf2);

        // 创建另一个复合节点,并添加之前的复合节点和新的叶子节点
        Component root = new Composite("Root");
        root.add(composite);
        root.add(leaf3);

        // 执行操作
        root.operation();
    }

}

模式应用后案例

上面文件与目录的案例,使用组合模式之后的代码实现如下。

public interface IComponent {//接口
    void display();
}
public class File implements IComponent{//文件实现

    private final String name;

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

    @Override
    public void display() {
        System.out.println("File: " + this.name);
    }

}
public class Directory implements IComponent{//目录实现

    private String name;
    private final List children;

    // 初始化方法
    public Directory(String name){
        this.name = this.name;
        this.children = new ArrayList<>();
    }

    // 添加子节点
    public void addComponent(IComponent component){
        this.children.add(component);
    }

    // 显示目录内容
    @Override
    public void display() {
       //System.out.println("Directory: " + this.name);
        for (IComponent child : this.children) {
            child.display();
        }
    }
}

public class Client {//调用方代码

    public static void main(String[] ars){

        Directory root= new Directory("Root");
        File file1 = new File("file1.txt");
        File file2 = new File ("file2.txt");
        root.addComponent(file1);
        root.addComponent(file2);

        Directory subDirectory =new Directory ("Subdirectory");

        File file3 = new File("file3.txt");
        File file4 = new File("file4.txt");
        subDirectory.addComponent(file3);
        subDirectory.addComponent(file4);

        root.addComponent(subDirectory);

        root.display();
    }
}

在上述代码中,由于树的结构使用一个接口和实现的家族来实现,这样树的结构中所有类的行为都是一致的,简化了编码时的复杂度。

适用场景

当需求中出现的一系列概念或对象,它们之间存在部分-整体的层次结构或共同构成一颗树的结构时,就可以考虑使用组合模式。

模式可能存在的困惑

困惑1:组合模式中的“组合”,与“组合优于继承”中的“组合”,有什么关联?

两者都代表了一种关系。前者的“组合”指的是将一系列对象按照层次化结构进行组织。而后者的“组合”指的是两个对象之间的聚合或组合关系,以此来取代类之间继承关系。

本质

组合模式的本质在于提供了一种机制来处理对象之间的部分-整体关系,并且通过统一接口来简化调用方使用复杂层次结构时可能遇到的问题。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯