研磨设计模式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对象

何时选用

相关推荐
晨米酱5 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机10 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机11 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机11 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤11 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴1 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript
李广坤1 天前
工厂模式
设计模式