组合模式
定义一个类(或抽象类),类里面有一堆的自己,进行各种操作,适合树形结构的场景
- 定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端对单个对象和组合对象保持一致的处理方式
- 类型:结构型
- 适用场景:
- 客户端可以忽略组合对象与单个对象的差异时
- 处理一个树形结构时
- 优点:
- 清楚的定义分层次的复杂对象,表示对象的全部或部分层次
- 让客户端忽略了层次的差异,方便对整个层次结构进行控制
- 简化客户端代码
- 符合开闭原则
- 缺点:
- 限制类型时会比较复杂
- 使设计变得更加抽象
- 相关设计模式:
- 组合模式和访问者模式:进行组合应用,可以使用访问者模式访问组合模式的递归结构
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; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 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)