设计模式(八)组合模式 Composite
2024-08-30 06:06:14
- 组合模式:
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式适用于创建复杂的对象,这个对象包含某些个别的对象以及这些对象的组合。
从操作的角度而言,客户端对于 个别对象/组合 的操作是一致的。
- 模拟场景
如图所示,总公司下属有多个部门,而子公司可以视为多个部门的组合。
整个数据结构呈树状,完美契合组合模式的应用场景。
- UML:
在这个场景中:
- 个别对象 -> 人事部(HRDepartment)和财务部(FinanceDepartment)
- 个别对象的组合 -> 公司(Company)
- 无论是 Company 还是 Department,对于 Client 而言,都被当做 CompanyItem 使用。
- 从树形结构来理解,Department 是叶节点,Company 是非叶节点。
- 代码:
@Data
@AllArgsConstructor
@ToString
public abstract class CompanyItem { protected String name; protected void addCompanyItem(CompanyItem companyItem) {
throw new UnsupportedOperationException("Not support to add companyItem");
} protected void removeCompanyItem(CompanyItem companyItem) {
throw new UnsupportedOperationException("Not support to remove companyItem");
} protected abstract void lineOfDuty(); protected abstract void showStructure(int depth);
}
public final class Company extends CompanyItem { private List<CompanyItem> childCompanyItems = new ArrayList<>(); public Company(String name) {
super(name);
} @Override
public void addCompanyItem(CompanyItem component) {
childCompanyItems.add(component);
} @Override
public void removeCompanyItem(CompanyItem component) {
childCompanyItems.remove(component);
} @Override
public void lineOfDuty() {
childCompanyItems.forEach(companyItem -> companyItem.lineOfDuty());
} @Override
public void showStructure(int depth) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < depth; ++i) {
builder.append("-");
}
System.out.println(builder.append(name));
childCompanyItems.forEach(companyItem -> companyItem.showStructure(depth + 1));
}
}
public final class FinanceDepartment extends CompanyItem { public FinanceDepartment(String name) {
super(name);
} @Override
public void lineOfDuty() {
System.out.println(name + ", treasurer is in charge of payroll");
} @Override
public void showStructure(int depth) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < depth; ++i) {
builder.append("-");
}
System.out.println(builder.append(name));
}
}
public final class HRDepartment extends CompanyItem { public HRDepartment(String name) {
super(name);
} @Override
public void lineOfDuty() {
System.out.println(name + ", HR is responsible for recruiting new employees");
} @Override
public void showStructure(int depth) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < depth; ++i) {
builder.append("-");
}
System.out.println(builder.append(name));
}
}
- 客户端调用:
private CompanyItem createParentCompany() {
CompanyItem parentCompany = new Company("Shanghai parent company");
parentCompany.addCompanyItem(new HRDepartment("Parent company HR department"));
CompanyItem southChildCompany = new Company("South child company");
southChildCompany.addCompanyItem(new HRDepartment("South child company HR department"));
parentCompany.addCompanyItem(southChildCompany);
CompanyItem hongKongOffice = new Company("HongKong office");
hongKongOffice.addCompanyItem(new FinanceDepartment("Hongkong office Finance department"));
southChildCompany.addCompanyItem(hongKongOffice);
parentCompany.addCompanyItem(new FinanceDepartment("Parent company Finance department"));
return parentCompany;
} @Test
void testComposite() {
CompanyItem parentCompany = createParentCompany();
parentCompany.showStructure(1);
System.out.println("===========================");
parentCompany.lineOfDuty();
}
- 输出:
最新文章
- svn清理失败且路径显示乱码
- 屠龙之路_击败DB小boss_FifthDay
- Linux---从start_kernel到init进程启动
- ADO访问Access数据库错误解决心得随笔
- mongodb操作:利用javaScript封装db.collection.find()后可调用函数源码解读
- tab奇偶行颜色交替+插件
- Filter ,Interceptor,AOP
- HDU1223 Order Count 动态规划 组合数
- bootstrap-table 表格加载中....处理
- 9.8、Libgdx的返回键和菜单键捕获
- Docker入门(三)使用Docker Compose
- openKM部署二次开发,eclipse环境
- mysql登录密码相关
- Luogu 3698 [CQOI2017]小Q的棋盘
- 关于ProjectServer定制化项目中心页面
- ManicTime软件破解版自用
- Rainmeter如何打开控制面板的小程序
- Android5.0以后,materialDesign风格的加阴影和裁剪效果
- [置顶]
 kubernetes资源类型--Service
- MongoDB增删改查操作详解(命令行)