组合模式

定义一个类(或抽象类),类里面有一堆的自己,进行各种操作,适合树形结构的场景

  • 定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端对单个对象和组合对象保持一致的处理方式
  • 类型:结构型
  • 适用场景:
    •   客户端可以忽略组合对象与单个对象的差异时
    •   处理一个树形结构时
  • 优点:
    •   清楚的定义分层次的复杂对象,表示对象的全部或部分层次
    •   让客户端忽略了层次的差异,方便对整个层次结构进行控制
    •   简化客户端代码
    •   符合开闭原则
  • 缺点:
    •   限制类型时会比较复杂
    •   使设计变得更加抽象
  • 相关设计模式:
    •   组合模式和访问者模式:进行组合应用,可以使用访问者模式访问组合模式的递归结构

Coding

复制代码
public abstract class AbCatalogComponent {
    public void add(AbCatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持添加操作");
    }

    public void remove(AbCatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持删除操作");
    }

    public String getName(AbCatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持获取名称操作");
    }

    public double getPrice(AbCatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持获取价格操作");
    }

    public void print(){
        throw new UnsupportedOperationException("不支持打印操作");
    }
}
/**
 * 课程信息
 */
public class Course extends AbCatalogComponent {
    private String name;
    private double price;

    public Course(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName(AbstractDecorator catalogComponent) {
        return this.name;
    }

    @Override
    public double getPrice(AbCatalogComponent catalogComponent) {
        return this.price;
    }

    @Override
    public void print() {
        System.out.println("Course Name:" + name + " Price:" + price);
    }
}
public class CourseCatalog extends AbCatalogComponent {
    private List<AbCatalogComponent> items = new ArrayList<AbCatalogComponent>();
    private String name;
    private Integer level;

    public CourseCatalog(String name,Integer level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void add(AbCatalogComponent catalogComponent) {
        items.add(catalogComponent);
    }

    @Override
    public String getName(AbCatalogComponent catalogComponent) {
        return this.name;
    }

    @Override
    public void remove(AbCatalogComponent catalogComponent) {
        items.remove(catalogComponent);
    }

    @Override
    public void print() {
        System.out.println(this.name);
        for (AbCatalogComponent catalogComponent : items) {
            if (this.level != null) {
                for (int i = 0; i < this.level; i++) {
                    System.out.print("  ");
                }
            }
            catalogComponent.print();
        }
    }
}
复制代码

 

测试

复制代码
public class Test {
    public static void main(String[] args) {
        AbCatalogComponent linuxCourse = new Course("Linux课程",11);
        AbCatalogComponent windowsCourse = new Course("Windows课程",11);

        AbCatalogComponent javaCourseCatalog = new CourseCatalog("Java课程目录",2);

        AbCatalogComponent mmallCourse1 = new Course("Java电商一期",55);
        AbCatalogComponent mmallCourse2 = new Course("Java电商二期",66);
        AbCatalogComponent designPattern = new Course("Java设计模式",77);

        javaCourseCatalog.add(mmallCourse1);
        javaCourseCatalog.add(mmallCourse2);
        javaCourseCatalog.add(designPattern);

        AbCatalogComponent imoocMainCourseCatalog = new CourseCatalog("课程主目录", 1);
        imoocMainCourseCatalog.add(linuxCourse);
        imoocMainCourseCatalog.add(windowsCourse);
        imoocMainCourseCatalog.add(javaCourseCatalog);

        imoocMainCourseCatalog.print();
    }
}
===============打印结果====================
课程主目录
  Course Name:Linux课程 Price:11.0
  Course Name:Windows课程 Price:11.0
  Java课程目录
    Course Name:Java电商一期 Price:55.0
    Course Name:Java电商二期 Price:66.0
    Course Name:Java设计模式 Price:77.0
复制代码

UML

说明:可以看代码或者UML类图,其核心在于类目和课程都继承了相同的类,然后类目中一对多组合了它们的基类对象,这就使得类目中可以添加课程也可以添加类目,要注意的问题是不同层次的类目或课程如果要做分层显示(比如每多一个子类层次,前面空格增加),是需要多做处理的,比如传入某个层级的值对不同层级做不同处理等

源码中的应用

  • java.awt.Container:可以看到add方法,添加了它的一个父类
public class Container extends Component {
    ...
    public Component add(Component comp) {
        addImpl(comp, null, -1);
        return comp;
    }
    ...
}
  • org.apache.ibatis.scripting.xmltags.MixedSqlNode:MyBatis中拼装各种sql用的模式就是组合模式
复制代码
public class MixedSqlNode implements SqlNode {
    private List<SqlNode> contents;

    public MixedSqlNode(List<SqlNode> contents) {
        this.contents = contents;
    }

    public boolean apply(DynamicContext context) {
        Iterator i$ = this.contents.iterator();

        while(i$.hasNext()) {
            SqlNode sqlNode = (SqlNode)i$.next();
            sqlNode.apply(context);
        }
        return true;
    }
}
复制代码

 

posted @   wangzhilei  阅读(5)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示