前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式-组合模式

设计模式-组合模式

作者头像
逍遥壮士
发布2020-09-18 11:24:41
6890
发布2020-09-18 11:24:41
举报
文章被收录于专栏:技术趋势

背景

世界分为7大洲,每个国家,一般只属一个洲(像俄罗斯这种除外哈),这样的话就构建成级联关系,一般世界上任何某处地区都所属某个国家,而这个国家又所属某个洲,组合模式是就是将地区(基本对象)和组合对象(国家、洲)不断的去组合成更复杂的的对象。将所有的地区组成树型结构;

组合模式是什么?

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

组合模式的安全性:从客户使用组合模式上看是否更安全。如果是安全的,那么就不会有发生误操作的可能,能访问的方法都是被支持的功能。

组合模式的透明性:从客户使用组合模式上看是否需要区分到底是组合对象还是叶子对象。如果是透明的,那就不用再区分,对于客户而言,都是组件对象,具体的类型对于客户而言是透明的,是客户无须关心的。

包含的角色有:

抽象组件:(Component)角色:这是一个抽象角色,它给参加组合的对象规定一个接口。这个角色给出共有的接口及其默认行为。

叶子对象:(Leaf)角色:代表参加组合的树叶对象。一个树叶没有下级的子对象。定义出参加组合的原始对象的行为。

容器对象:(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象行为。

组合模式可以干嘛?

该模式主要是解决树型结构遍历和递归处理的问题;

优点:

易拓展:节点可以自由增加,遵循了开闭原则;

统一了组合对象和叶子对象,子节点和父节点统一类型;

缺点:

破坏了单一职责,又获取父节点又打印子结点破坏了单一职责;

组合模式类图

源码下载:https://gitee.com/hong99/design-model/issues/I1IMES

实现代码

  • 安全模式
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/25 18:08
 * @Description:抽象的位置(抽象构件)
 */
public interface IPosition {
    /**
     *
     * 功能描述:输出位置名称
     *
     * @param: 
     * @return: 
     * @auther: csh
     * @date: 2020/5/25 18:09
     */
    void printPositionName(String preStr);
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/25 18:13
 * @Description:洲
 */
public class Continent implements IPosition {
    /**
     *
     * 功能描述:各地方
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:14
     */
    private List<IPosition>  childPosition = new ArrayList <IPosition>();
    /**
     *
     * 功能描述:地方名称
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:14
     */
    private String name;

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

    public String getName() {
        return name;
    }
    /**
     *
     * 功能描述:添加
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:16
     */
    public void addChild(IPosition child){
        childPosition.add(child);
    }
    /**
     *
     * 功能描述:删除
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:16
     */
    public void removeChild(IPosition position){
        childPosition.remove(position);
    }
    /**
     *
     * 功能描述:返回列表
     *
     * @param: 
     * @return: 
     * @auther: csh
     * @date: 2020/5/25 18:16
     */
    public List<IPosition> getChild(){
        return childPosition;
    }



    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void printPositionName(String preStr) {
        //当前的位置
        System.out.println(preStr+"+"+this.name);
        //获取包含的地区
        if(null!=childPosition && childPosition.size()>0){
            preStr+=" ";
            for (IPosition iPosition : childPosition) {
                iPosition.printPositionName(preStr);
            }
        }
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/25 18:33
 * @Description:国家
 */
public class Country implements IPosition {

    /**
     *
     * 功能描述:地方名称
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:14
     */
    private String name;

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

    @Override
    public void printPositionName(String preStr) {
        System.out.println(preStr + "-" + name);
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/25 18:36
 * @Description:演示  (安全模式)
 */
public class Client {
    public static void main(String[] args) {
        Continent earth = new Continent("地球");
        Continent asian = new Continent("亚洲");
        Continent america = new Continent("美洲");
        Continent africa = new Continent("非洲");


        Country china = new Country("中国");
        asian.addChild(china);
        Country american = new Country("美国");
        america.addChild(american);
        Country cameroon = new Country("喀麦隆");
        africa.addChild(cameroon);

        earth.addChild(asian);
        earth.addChild(america);
        earth.addChild(africa);

        earth.printPositionName("");
        
    }
}

结果

代码语言:javascript
复制
+地球
 +亚洲
  -中国
 +美洲
  -美国
 +非洲
  -喀麦隆

透明模式

代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/25 18:13
 * @Description:抽象的地方(组件)
 */
public abstract class IPosition  {

    /**
     *
     * 功能描述:打印位置名称
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/25 18:58
     */
    public abstract void printPositionName(String preStr);
    /**
     *
     * 功能描述: 添加子类
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/26 9:38
     */
    public  void addChild(IPosition child){
        throw  new UnsupportedOperationException("对象不支持此功能");
    }
    /**
     *
     * 功能描述:删除子类
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/26 9:38
     */
    public  void removeChild(IPosition child){
        throw  new UnsupportedOperationException("对象不支持此功能");
    }
    /**
     *
     * 功能描述:获取所有子类
     *
     * @param:
     * @return:
     * @auther: csh
     * @date: 2020/5/26 9:40
     */
    public List<IPosition> getChild(){
        throw  new UnsupportedOperationException("对象不支持此功能");
    }


}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/26 09:41
 * @Description:洲
 */
public class Continent extends IPosition {

    /**
     *
     * 功能描述:子类集合
     *
     * @param: 
     * @return: 
     * @auther: csh
     * @date: 2020/5/26 9:42
     */
    private List<IPosition> childList = new ArrayList <IPosition>();

    /**
     *
     * 功能描述:对象名称
     *
     * @param: 
     * @return: 
     * @auther: csh
     * @date: 2020/5/26 9:42
     */
    private String name;

    @Override
    public void printPositionName(String preStr) {
        //当前的位置
        System.out.println(preStr+"+"+this.name);
        //获取包含的地区
        if(null!=childList && childList.size()>0){
            preStr+=" ";
            for (IPosition iPosition : childList) {
                iPosition.printPositionName(preStr);
            }
        }
    }


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

    @Override
    public void removeChild(IPosition child) {
        childList.remove(child);
    }

    @Override
    public void addChild(IPosition child){
        childList.add(child);
    }

    @Override
    public List <IPosition> getChild() {
        return childList;
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/26 10:23
 * @Description:国家
 */
public class Country extends IPosition{

    private String name;

    public Country(String name) {
        this.name = name;
    }
    
    @Override
    public void printPositionName(String preStr) {
        System.out.println(preStr+"-"+name);
    }
}
代码语言:javascript
复制
/**
 * @Auther: csh
 * @Date: 2020/5/26 10:25
 * @Description:透明模式
 */
public class Client {

    public static void main(String[] args) {
        Continent earth = new Continent("地球");
        Continent america = new Continent("美洲");
        Continent asian = new Continent("亚洲");
        Continent africa = new Continent("非洲");

        Country china = new Country("中国");
        asian.addChild(china);
        Country american = new Country("美国");
        america.addChild(american);
        Country cameroon = new Country("喀麦隆");
        africa.addChild(cameroon);

        earth.addChild(asian);
        earth.addChild(america);
        earth.addChild(africa);

        earth.printPositionName("");

    }
}
代码语言:javascript
复制
+地球
 +亚洲
  -中国
 +美洲
  -美国
 +非洲
  -喀麦隆

源码下载:https://gitee.com/hong99/design-model/issues/I1IMES

最后

实际使用过程中,透明模式使用得比较多,但是建议在使用该模式的时候加上缓存 redis或者本地缓存,这样的效率更高,没必要每次都去遍历,这样太浪费性能了,而且如需要遍历,建议使用jdk8的新特性来处理。至于本文主要都是从上到下的模式,其他还有从下到上的查询以及同级别的查找,这里就不一一列举了,熟悉本文后可以灵活变通。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
  • 源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
  • 最后
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档