设计模式之组合模式

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

结构

组合模式结构图
组合模式的主要角色分为:

  • 抽象组件角色(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
  • 叶子角色(Leaf):在组合中表示子节点对象,实现了Component,其下没有分支了。
  • 组合角色(Composite):一个组合组件,其下有叶子节点,实现了Component。

优缺点

优点:

  • 组合模式屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),将客户代码与复杂的容器对象解耦,使得客户端可以忽略层次间的差异,使用一致的行为控制不同层次。
  • 在 组合模式可以很方便地增加树枝节点和叶子节点 对象,并对现有类库无侵入,符合开闭原则。

缺点:

  • 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系。
  • 组合模式在具体实现上违背了设计模式 接口隔离原则 或 依赖倒置原则。

代码实现

组合模式分为透明式的组合模式和安全式的组合模式。
透明式组合模式:把所有公共方法都定义在 Component 中,这样做的好处是客户端无需分辨是叶子节点(Leaf)和组合节点(Composite),它们具备完全一致的接口;缺点是叶子节点(Leaf)需要实现一些本来不需要的方法,这就破环了接口隔离原则。

/**
*透明组合模式
*/
package com.yn.design_pattern.composite.universal.transparent;

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

class Client {
    public static void main(String[] args) {
        // 来一个根节点
        Component root = new Composite("root");
        // 来一个树枝节点
        Component branchA = new Composite("---branchA");
        Component branchB = new Composite("------branchB");
        // 来一个叶子节点
        Component leafA = new Leaf("------leafA");
        Component leafB = new Leaf("---------leafB");
        Component leafC = new Leaf("---leafC");

        root.addChild(branchA);
        root.addChild(leafC);
        branchA.addChild(leafA);
        branchA.addChild(branchB);
        branchB.addChild(leafB);

        String result = root.operation();
        System.out.println(result);

    }

    // 抽象根节点
    static abstract class Component {
        protected String name;

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

        public abstract String operation();

        public boolean addChild(Component component) {
            throw new UnsupportedOperationException("addChild not supported!");
        }

        public boolean removeChild(Component component) {
            throw new UnsupportedOperationException("removeChild not supported!");
        }

        public Component getChild(int index) {
            throw new UnsupportedOperationException("getChild not supported!");
        }
    }

    // 树节点
    static class Composite extends Component {
        private List<Component> mComponents;

        public Composite(String name) {
            super(name);
            this.mComponents = new ArrayList<>();
        }

        @Override
        public String operation() {
            StringBuilder builder = new StringBuilder(this.name);
            for (Component component : this.mComponents) {
                builder.append("\n");
                builder.append(component.operation());
            }
            return builder.toString();
        }

        @Override
        public boolean addChild(Component component) {
            return this.mComponents.add(component);
        }

        @Override
        public boolean removeChild(Component component) {
            return this.mComponents.remove(component);
        }

        @Override
        public Component getChild(int index) {
            return this.mComponents.get(index);
        }
    }

    //叶子节点
    static class Leaf extends Component {

        public Leaf(String name) {
            super(name);
        }

        @Override
        public String operation() {
            return this.name;
        }
    }
}

安全组合模式:统一行为(Component)只规定系统各个层次的最基础的一致行为,而把组合(树节点)本身的方法(管理子类对象的添加,删除等)放到自身当中。这样做的好处是接口定义职责清晰,符合设计模式 单一职责原则和接口隔离原则;缺点是客户需要区分树枝节点(Composite)和叶子节点(Leaf),这样才能正确处理各个层次的操作,客户端无法依赖抽象(Component),违背了设计模式依赖倒置原则。
安全组合模式相对于透明组合模式需进行修改代码如下:

/**
*安全组合模式
*/

    // 抽象根节点
    static abstract class Component {
        protected String name;

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

        public abstract String operation();
    }
class Client {
    public static void main(String[] args) {
        // 来一个根节点
        Composite root = new Composite("root");
        // 来一个树枝节点
        Composite branchA = new Composite("---branchA");
        Composite branchB = new Composite("------branchB");
        // 来一个叶子节点
        Component leafA = new Leaf("------leafA");
        Component leafB = new Leaf("---------leafB");
        Component leafC = new Leaf("---leafC");

        root.addChild(branchA);
        root.addChild(leafC);
        branchA.addChild(leafA);
        branchA.addChild(branchB);
        branchB.addChild(leafB);

        String result = root.operation();
        System.out.println(result);
    }
}

控制台输出结果:

root
---branchA
------leafA
------branchB
---------leafB
---leafC
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值