• 设计模式之组合模式


     

    什么是组合模式

            组合模式(Composite Pattern)是一种结构型设计模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的关系。组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象。

    组合模式的核心角色

    1. 抽象构件(AbstractComponent)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
    2. 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
    3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

    组合模式如何实现

            这里举一个例子来说明如何实现组合模式以及组合模式的适用场景。比如XXX上市的科技公司的组织架构如上图,需要展示一下它的的组织架构,这个程序应该怎么写呢?这个场景就比较适合使用组合模式,先来画一下UML类图:

    1. AbstractOrganization:抽象组织类,属于抽象构件角色,定义了树叶构件、树枝构件的共同行为;
    2. Company、BranchCompany:总公司实体类、分公司实体类,继承于抽象组织类,属于树枝构件角色,树枝构件与树叶构件最明显的区别就是,树枝构件中包含有子节点,另外还添加、移除子节点构件的能力;
    3. Department:部门实体类,继承于抽象组织类,属于树叶节点构件,树叶节点构件没有子节点,所以也就没有必要重写添加、移除子节点的方法;
    1. /**
    2. * 抽象组织,抽象构件(AbstractComponent)角色
    3. */
    4. public abstract class AbstractOrganization {
    5. /**
    6. * 组织名称
    7. *
    8. * @return
    9. */
    10. public abstract String getOrgName();
    11. /**
    12. * 组织实际领导
    13. *
    14. * @return
    15. */
    16. public abstract String getLeaderName();
    17. /**
    18. * 添加组织
    19. *
    20. * @param abstractOrganization
    21. */
    22. public void add(AbstractOrganization abstractOrganization) {
    23. }
    24. /**
    25. * 移除组织
    26. *
    27. * @param abstractOrganization
    28. */
    29. public void remove(AbstractOrganization abstractOrganization) {
    30. }
    31. /**
    32. * 组织信息展示
    33. */
    34. public void show() {
    35. }
    36. }
    1. /**
    2. * 分公司 ,树枝构件(Composite)角色
    3. */
    4. public class BranchCompany extends AbstractOrganization {
    5. /**
    6. * 组织名称
    7. */
    8. private String orgName;
    9. /**
    10. * 组织实际领导
    11. */
    12. private String leaderName;
    13. private List organizations = new ArrayList<>();
    14. public BranchCompany(String orgName, String leaderName) {
    15. this.orgName = orgName;
    16. this.leaderName = leaderName;
    17. }
    18. @Override
    19. public String getOrgName() {
    20. return this.orgName;
    21. }
    22. @Override
    23. public String getLeaderName() {
    24. return this.leaderName;
    25. }
    26. @Override
    27. public void add(AbstractOrganization abstractOrganization) {
    28. this.organizations.add(abstractOrganization);
    29. }
    30. @Override
    31. public void remove(AbstractOrganization abstractOrganization) {
    32. this.organizations.remove(abstractOrganization);
    33. }
    34. @Override
    35. public void show() {
    36. System.out.println("公司名称:" + this.orgName + ",主要领导:" + this.leaderName);
    37. for (AbstractOrganization organization : organizations) {
    38. organization.show();
    39. }
    40. }
    41. }
    1. /**
    2. * 总公司 ,树枝构件(Composite)角色
    3. */
    4. public class Company extends AbstractOrganization {
    5. private List organizations = new ArrayList<>();
    6. /**
    7. * 组织名称
    8. */
    9. private String orgName;
    10. /**
    11. * 组织实际领导
    12. */
    13. private String leaderName;
    14. public Company(String orgName, String leaderName) {
    15. this.orgName = orgName;
    16. this.leaderName = leaderName;
    17. }
    18. @Override
    19. public String getOrgName() {
    20. return this.orgName;
    21. }
    22. @Override
    23. public String getLeaderName() {
    24. return this.leaderName;
    25. }
    26. @Override
    27. public void add(AbstractOrganization abstractOrganization) {
    28. this.organizations.add(abstractOrganization);
    29. }
    30. @Override
    31. public void remove(AbstractOrganization abstractOrganization) {
    32. this.organizations.remove(abstractOrganization);
    33. }
    34. @Override
    35. public void show() {
    36. System.out.println("公司名称:" + this.orgName + ",主要领导:" + this.leaderName);
    37. for (AbstractOrganization organization : organizations) {
    38. organization.show();
    39. }
    40. }
    41. }
    1. /**
    2. * 部门 ,树叶构件(Leaf)角色
    3. */
    4. public class Department extends AbstractOrganization {
    5. /**
    6. * 组织名称
    7. */
    8. private String orgName;
    9. /**
    10. * 组织实际领导
    11. */
    12. private String leaderName;
    13. public Department(String orgName, String leaderName) {
    14. this.orgName = orgName;
    15. this.leaderName = leaderName;
    16. }
    17. @Override
    18. public String getOrgName() {
    19. return this.orgName;
    20. }
    21. @Override
    22. public String getLeaderName() {
    23. return this.leaderName;
    24. }
    25. @Override
    26. public void show() {
    27. System.out.println("部门名称:" + this.orgName + ",主要领导:" + this.leaderName);
    28. }
    29. }
    1. public class Test {
    2. public static void main(String[] args) {
    3. AbstractOrganization huawei = new Company("华为科技", "任正非");
    4. AbstractOrganization henan = new BranchCompany("河南分公司", "张三");
    5. huawei.add(henan);
    6. AbstractOrganization yanfabu = new Department("研发部", "小李");
    7. AbstractOrganization xiaoshoubu = new Department("销售部", "小张");
    8. henan.add(yanfabu);
    9. henan.add(xiaoshoubu);
    10. AbstractOrganization shangdong = new BranchCompany("山东分公司", "李四");
    11. huawei.add(shangdong);
    12. AbstractOrganization xiaoshoubu2 = new Department("销售部", "小美");
    13. AbstractOrganization caiwubu = new Department("财务部", "小花");
    14. shangdong.add(xiaoshoubu2);
    15. shangdong.add(caiwubu);
    16. huawei.show();
    17. }
    18. }

    组合模式的适用场景

    1. 构建复杂的树形结构
    2. 希望客户端忽略对象的差异
    3. 处理树形结构

    总结

    优点

    1. 创建灵活且易于扩展的软件产品,符合开闭原则。组合模式使得添加新类型的组件变得容易,因为这不需要修改现有的类或对象。这种灵活性有助于降低系统的复杂性,提高可维护性和可扩展性。
    2. 简化客户端代码。通过使用组合模式,客户端可以避免处理大量复杂的子系统类。相反,客户端只需要与抽象类或接口进行交互,这有助于简化客户端代码,减少开发人员的工作量。
    3. 易于维护和修改。由于组合模式使得系统结构清晰且易于理解,因此它有助于提高代码的可维护性和可修改性。当需要修改或添加新功能时,可以更容易地定位和替换组件,而不会影响到整个系统的稳定性。

    缺点

    1. 增加系统的复杂性和理解难度。使用组合模式需要设计出复杂的类层次结构,并且需要仔细考虑如何将组件组合在一起。这可能会增加系统的复杂性和理解难度,使得开发人员难以理解和维护代码。
    2. 需要正确地识别出系统中两个独立变化的维度。在组合模式中,需要将对象组合成树形结构来表示部分-整体的层次结构。这需要正确地识别出系统中两个独立变化的维度,并且需要将它们组合在一起。如果维度之间的关系不正确,可能会导致系统出现错误或不可维护。
    3. 需要对系统进行递归处理。由于组合模式使用递归结构来构建树形结构,因此需要对系统进行递归处理。这可能会导致处理时间变长,并且在某些情况下可能会出现性能问题。

            总之,组合模式适用于构建复杂的树形结构,希望客户端忽略组合对象与单个对象的差异,以及处理树形结构的场景。它能够清晰地定义分层次的复杂对象,简化客户端代码,符合开闭原则。但也存在一些缺点。在应用组合模式时,需要根据具体情况进行权衡,并考虑是否适合使用该模式。

     

  • 相关阅读:
    springboot项目整合swagger2
    Leangoo敏捷工具管理轻量级项目群
    基于VHDL的专业略缩词
    ansible 的安装及常见模块使用
    基于ChatGPT打造安全脚本工具流程
    循环神经网络RNN基础《PyTorch深度学习实践》
    Cadence的网格生成工具Pointwise 2023.2.3版本在Windows系统上的安装配置
    并发编程之Executor线程池原理与源码解读
    maven命令上传文件到私服deploy-file
    视频监控/视频汇聚/安防视频监控平台EasyCVR配置集群后有一台显示离线是什么原因?
  • 原文地址:https://blog.csdn.net/fox9916/article/details/134084129