Java DesignPartten Code

设计模式-组合模式

Posted on 2020-09-28,6 min read

定义

  • Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients
    treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表
    示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
  • 组合模式的结构就类似一棵树,只是它将数据结构中的树的树枝和树叶分开来了。
  • 组成:
    • Component抽象构件角色:定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性,比如我们例子
      中的getInfo就封装到了抽象类中。
    • Leaf叶子构件:叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
    • Composite树枝构件:树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
  • 通用类图
组合模式通用类图

优点

  • 高层模块调用简单:一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,也就是说高层模块不必关心自己处理的是单个对象还是整个组合机构,简化了高层模块的代码
  • 节点自由增加:如果想增加和删除一个节点都是很容易的(参考数据结构)

缺点

  • 树枝和树叶使用时候直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突

使用场景

  • 场景:
    • 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理
    • 从一个整体中能够独立出部分模块或功能的场景

代码

安全模式

安全模式是组合模式中的一种,类似树的一种结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

本项目使用类图

代码

总接口(抽象类

package com.pattern.composite;

public abstract class Component {
    // 对象的名字
    private String name;

    public String getName() {
        return name;
    }

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

    // 当前对象的老大
    private Component parent;
    /**
     * 个体和整体都具有的共享
     */
    public void doSomething(){
        System.out.println("这是共有的方法");
    }
    /**
     * 设置树枝,相当于设置老大是谁
     * @param parent
     */
    public void setParent(Component parent){
        this.parent = parent;
    }
}

树枝(继承自总接口

package com.pattern.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * 树枝,用企业的结构来将讲这个就是经理
 */
public class Composite extends Component {
    public Composite(String name) {
        super(name);
    }

    /**
     * 叶子的容器,放打工仔的
     */
    private List<Component> components = new ArrayList<>();
    // 当前树枝的老大
    private Component composite;
    /**
     * 添加叶子,给经理添加打工仔
     * @param component
     */
    public void add(Component component){
        this.components.add(component);
    }

    /**
     * 移除叶子,开除打工仔
     * @param component
     */
    public void remove(Component component){
        this.components.remove(component);
    }

    /**
     * 列出叶子,列出所有打工仔
     * @return
     */
    public List<Component> getComponents(){
        return this.components;
    }

}


树叶(继承自总接口

package com.pattern.composite;

/**
 * 叶子,拿企业来讲就是打工仔
 */
public class Leaf extends Component {
    public Leaf(String name){
        super(name);
    }
    // 当前叶子的老大
    private Component composite;
    public void LeafMethod(){
        System.out.println("叶子自己的方法");
    }
}

测试代码

package com.pattern;

import com.pattern.composite.Component;
import com.pattern.composite.Composite;
import com.pattern.composite.Leaf;
import org.junit.Test;

import java.util.List;

public class CompositeTest {

    @Test
    public void test() {
        // 定义一个大boss
        Composite boss = new Composite("总经理");
        // 定义几个部门经理
        Composite productManager = new Composite("产品经理");
        Composite salesManager = new Composite("销售经理");
        // 设置经理的老大为总经理
        boss.add(productManager);
        boss.add(salesManager);
        productManager.setParent(boss);
        salesManager.setParent(boss);
        // 定义几个打工仔
        Leaf programmerA = new Leaf("程序员A");
        Leaf programmerB = new Leaf("程序员B");
        Leaf programmerC = new Leaf("程序员C");
        Leaf sellerA = new Leaf("产品推销A");
        Leaf sellerB = new Leaf("产品推销B");
        // 给打工仔设置Boss
        productManager.add(programmerA);
        productManager.add(programmerB);
        productManager.add(programmerC);
        programmerA.setParent(productManager);
        programmerB.setParent(productManager);
        programmerC.setParent(productManager);
        salesManager.add(sellerA);
        salesManager.add(sellerB);
        sellerA.setParent(salesManager);
        sellerB.setParent(salesManager);
        // 循环输出
        List<Component> managers = boss.getComponents();
        for (int i = 0; i < managers.size(); i++) {
            System.out.println("总经理手下有:" + managers.get(i).getName());
        }
        for (int i = 0; i < productManager.getComponents().size(); i++) {
            System.out.println("产品经理手下有:" + productManager.getComponents().get(i).getName());
        }
        for (int i = 0; i < salesManager.getComponents().size(); i++) {
            System.out.println("销售经理手下有:" + salesManager.getComponents().get(i).getName());
        }

    }
}

结果

总经理手下有:产品经理
总经理手下有:销售经理
产品经理手下有:程序员A
产品经理手下有:程序员B
产品经理手下有:程序员C
销售经理手下有:产品推销A
销售经理手下有:产品推销B

Process finished with exit code 0

透明模式

  • 透明模式是把用来组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,如果处理不当会在运行期期间出现问题。并且不便于维护。此处只附上类图
透明模式通用类图

注意

  • 组合模式分为安全模式和透明模式,推荐使用透明模式
  • 将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
  • 组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。
  • 无论如何,树的组装是跑不了的,但是在实际的应用环境中,可以直接从数据库中提取出那些要分配到树枝,那些要分配到树叶。

下一篇: 设计模式-适配器模式→

loading...