研磨设计模式day13组合模式

目录

场景

不用模式实现

代码实现

有何问题

解决方案

代码改造

组合模式优缺点

思考

何时选用


场景

不用模式实现

代码实现

叶子对象

java 复制代码
package day14组合模式;

/**
 * 叶子对象
 */
public class Leaf {
    /**
     * 叶子对象的名字
     */
    private String name = "";

    /**
     * 构造方法,传入叶子对象的名字
     */
    public Leaf(String name){
        this.name = name;
    }

    /**
     * 输出叶子对象的结构
     */
    public void printStruct(String preStr){
        System.out.println(preStr + "_" + name);
    }
}

组合对象

java 复制代码
package day14组合模式;

import java.util.ArrayList;
import java.util.Collection;

/**
 * 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
 * 由于类型不同,需要分开记录
 */
public class Composite {
    /**
     * 用来记录包含的其他组合对象
     */
    private Collection<Composite> childComposite = new ArrayList<>();

    /**
     * 用来记录包含的其他叶子对象
     */
    private Collection<Leaf> childLeaf = new ArrayList<>();

    /**
     * 组合对象的名字
     */
    private String name = "";
    /**
     * 构造方法
     */
    public Composite(String name){
        this.name = name;
    }

    /**
     * 向组合对象加入被它包含的其他组合对象
     * @param c 被它包含的其他组合对象
     */
    public void addComposite(Composite c){
        this.childComposite.add(c);
    }

    /**
     * 向组合对象加入被它包含的叶子对象
     * @param leaf 被它包含的叶子对象
     */
    public void addLeaf(Leaf leaf){
        this.childLeaf.add(leaf);
    }

    /**
     * 输出组合对象自身的结构
     */
    public void printStruct(String prestr){
        // 先把自己输出去
        System.out.println(prestr + "+" + this.name);
        // 然后添加一个空格,表示向后缩进一个空格,输出自己包含的叶子对象
        prestr += " ";
        for (Leaf leaf : childLeaf) {
            leaf.printStruct(prestr);
        }
        // 输出当前对象的子对象了
        for (Composite c : childComposite) {
            // 递归输出每个子对象
            c.printStruct(prestr);
        }
    }
}

Client

java 复制代码
package day14组合模式;

public class Client {
    public static void main(String[] args) {
        // 定义所有的组合对象
        Composite root = new Composite("服装");
        Composite c1 = new Composite("男装");
        Composite c2 = new Composite("女装");

        // 定义所有的叶子对象
        Leaf leaf1 = new Leaf("衬衣");
        Leaf leaf2 = new Leaf("夹克");
        Leaf leaf3 = new Leaf("裙子");
        Leaf leaf4 = new Leaf("套装");

        // 按照树的结构来组合 组合对象和叶子对象
        root.addComposite(c1);
        root.addComposite(c2);
        c1.addLeaf(leaf1);
        c1.addLeaf(leaf2);
        c2.addLeaf(leaf3);
        c2.addLeaf(leaf4);

        // 调用跟对象的输出功能来输出整棵树
        root.printStruct("");
    }
}

有何问题

必须区分组合对象和叶子对象,并进行有区别的对待

解决方案

组合模式

定义:

思路:将组合对象和叶子对象统一起来。通过引入一个抽象的组件对象,作为组合对象和叶子对象的父对象,这样就统一起来了。

代码改造

抽象父组件对象

java 复制代码
package day14组合模式.Component;

/**
 * 抽象的父组件对象
 */
public abstract class Component {
    /**
     * 输出组件自身的名称
     */
    public abstract void printStruct(String preStr);

    /**
     * 向组合对象中加入组件对象
     * @param child
     */
    public void addChild(Component child){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }

    /**
     * 从组合对象中移出某个组件对象
     * @param child
     */
    public void removeChild(Component child){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }

    /**
     * 返回某个索引对应的组件对象
     * @param index 需要获取的组件对象的索引,索引从0开始
     * @return 索引对应的组件对象
     */
    public Component getChildren(int index){
        throw new UnsupportedOperationException("对象不支持这个功能");
    }
}

Leaf类

继承一下这个抽象类,别的没有变化

java 复制代码
package day14组合模式;

import day14组合模式.Component.Component;

/**
 * 叶子对象
 */
public class Leaf extends Component {
    /**
     * 叶子对象的名字
     */
    private String name = "";

    /**
     * 构造方法,传入叶子对象的名字
     */
    public Leaf(String name){
        this.name = name;
    }

    /**
     * 输出叶子对象的结构
     */
    public void printStruct(String preStr){
        System.out.println(preStr + name);
    }
}

组合对象类

java 复制代码
package day14组合模式;

import day14组合模式.Component.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 组合对象,组合对象里面包含其他的组合对象或者是叶子对象
 * 由于类型不同,需要分开记录
 */
public class Composite extends Component {

    /**
     * 用来存储组合对象中包含的子组件对象
     */
    private List<Component> childComponents = null;

    /**
     * 组合对象的名字
     */
    private String name = "";

    /**
     * 构造方法
     */
    public Composite(String name) {
        this.name = name;
    }


    public void addChild(Component child) {
        // 延迟初始化
        if (childComponents == null) {
            childComponents = new ArrayList<>();
        }
        childComponents.add(child);
    }

    /**
     * 输出组合对象自身的结构
     */
    public void printStruct(String prestr) {
        // 先把自己输出去
        System.out.println(prestr + this.name);
        // 如果还包含有子组件,那么就输出这些子组件对象
        if (this.childComponents != null) {
            prestr += " ";
            // 输出当前对象的子对象了
            for (Component c : childComponents) {
                // 递归输出每个子对象
                c.printStruct(prestr);
            }
        }

    }
}

去掉了之前区分组合对象和叶子对象的方法。

Client

java 复制代码
        // 定义所有的组合对象
        Component root = new Composite("服装");
        Component c1 = new Composite("男装");
        Component c2 = new Composite("女装");

        // 定义所有的叶子对象
        Component leaf1 = new Leaf("衬衣");
        Component leaf2 = new Leaf("夹克");
        Component leaf3 = new Leaf("裙子");
        Component leaf4 = new Leaf("套装");

        // 按照树的结构来组合 组合对象和叶子对象
        root.addChild(c1);
        root.addChild(c2);
        c1.addChild(leaf1);
        c1.addChild(leaf2);
        c2.addChild(leaf3);
        c2.addChild(leaf4);

        // 调用跟对象的输出功能来输出整棵树
        root.printStruct("");

组合模式优缺点

思考

本质:统一叶子对象和组合对象,一视同仁全部当成Component对象

何时选用

相关推荐
ok!ko2 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
拉里小猪的迷弟3 小时前
设计模式-创建型-常用:单例模式、工厂模式、建造者模式
单例模式·设计模式·建造者模式·工厂模式
严文文-Chris5 小时前
【设计模式-中介者模式】
设计模式·中介者模式
刷帅耍帅5 小时前
设计模式-中介者模式
设计模式·中介者模式
刷帅耍帅6 小时前
设计模式-组合模式
设计模式·组合模式
刷帅耍帅7 小时前
设计模式-命令模式
设计模式·命令模式
码龄3年 审核中7 小时前
设计模式、系统设计 record part03
设计模式
刷帅耍帅7 小时前
设计模式-外观模式
设计模式·外观模式
刷帅耍帅8 小时前
设计模式-迭代器模式
设计模式·迭代器模式
liu_chunhai8 小时前
设计模式(3)builder
java·开发语言·设计模式