研磨设计模式day13组合模式

目录

场景

不用模式实现 

代码实现 

有何问题 

解决方案

代码改造 

组合模式优缺点

思考 

何时选用


场景

研磨设计模式day13组合模式_第1张图片

不用模式实现 

研磨设计模式day13组合模式_第2张图片

代码实现 

叶子对象

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);
    }
}

组合对象

package day14组合模式;

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

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

    /**
     * 用来记录包含的其他叶子对象
     */
    private Collection 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

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("");
    }
}

研磨设计模式day13组合模式_第3张图片

有何问题 

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

解决方案

组合模式

定义:

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

代码改造 

抽象父组件对象

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类

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

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);
    }
}

组合对象类

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 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

        // 定义所有的组合对象
        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("");

研磨设计模式day13组合模式_第4张图片

组合模式优缺点

研磨设计模式day13组合模式_第5张图片

研磨设计模式day13组合模式_第6张图片 

思考 

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

何时选用

研磨设计模式day13组合模式_第7张图片

 

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