合成模式

1.定义

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

2.实现

合成(Composite)模式属于结构型设计模式.它将对象组合成树形结构以表示“整体-部分”的层次结构,定义了包含基本对象和组合对象的类层次结构,使得用户对单个对象和组合对象的使用具有一致性.合成模式就是一个处理对象的树结构的模式.合成模式把部分与整体的关系用树结构表示出来,使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待.

合成(Composite)模式

  • 抽象构件(Component)角色: 给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象.
  • 树枝构件(Composite)角色: 代表参加组合的有下级子对象的对象,树枝构件类给出所有的管理子对象的方法.
  • 树叶构件(Leaf)角色: 是没下级子对象的对象,定义出参加组合的原始对象的行为.

合成模式

public interface Component {
    /**
     * 输出组建自身的名称
     * @param preStr    前缀
     */
    void printStructure(String preStr);
}


public class Composite implements Component {
    /**
     * 用来存储组合对象中包含的子组件对象
     */
    private List<Component> childComponents = new ArrayList<Component>();
    /**
     * 组合对象的名字
     */
    private String name;

    /**
     * 构造方法,传入组合对象的名字
     *
     * @param name 组合对象的名字
     */
    public Composite(String name) {
        this.name = name;
    }

    /**
     * 聚集管理方法,增加一个子构件对象
     *
     * @param child 子构件对象
     */
    public void addChild(Component child) {
        childComponents.add(child);
    }

    /**
     * 聚集管理方法,删除一个子构件对象
     *
     * @param index 子构件对象的下标
     */
    public void removeChild(int index) {
        childComponents.remove(index);
    }

    /**
     * 聚集管理方法,返回所有子构件对象
     */
    public List<Component> getChild() {
        return childComponents;
    }

    /**
     * 输出对象的自身结构
     *
     * @param preStr 前缀,主要是按照层级拼接空格,实现向后缩进
     */
    @Override
    public void printStructure(String preStr) {
        // 先把自己输出
        System.out.println(preStr + "+" + this.name);
        //如果还包含有子组件,那么就输出这些子组件对象
        if (this.childComponents != null) {
            //添加两个空格,表示向后缩进两个空格
            preStr += "  ";
            //输出当前对象的子对象
            for (Component c : childComponents) {
                //递归输出每个子对象
                c.printStructure(preStr);
            }
        }
    }
}

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

    /**
     * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
     * @param preStr   前缀,主要是按照层级拼接的空格,实现向后缩进
     */
    @Override
    public void printStructure(String preStr) {
        System.out.println(preStr + "-" + name);
    }
}

客户端

public class CompositeClient {
    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.addChild(c1);
        root.addChild(c2);

        c1.addChild(leaf1);
        c1.addChild(leaf2);

        c2.addChild(leaf3);
        c2.addChild(leaf4);

        root.printStructure("");
    }
}

3.方式说明

组合模式的两种实现方法

  • 安全性合成模式是指: 从客户端使用合成模式上看是否更安全,如果是安全的,那么就不会有发生误操作的可能,能访问的方法都是被支持的.
  • 透明性合成模式是指: 从客户端使用合成模式上,是否需要区分到底是"树枝对象"还是"树叶对象".如果是透明的,那就不用区分,对于客户而言,都是Compoent对象,具体的类型对于客户端而言是透明的,是无须关心的.

对于合成模式而言,在安全性和透明性上,会更看重透明性,毕竟合成模式的目的是:让客户端不再区分操作的是树枝对象还是树叶对象,而是以一个统一的方式来操作. 而且对于安全性的实现,需要区分是树枝对象还是树叶对象.有时候,需要将对象进行类型转换,却发现类型信息丢失了,只好强行转换,这种类型转换必然是不够安全的.

results matching ""

    No results matching ""