Java设计模式----组合模式(composite)

1.什么是组合模式

对于树形结构,当容器对象(如文件夹)的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象(可以是容器对象,也可以是叶子对象)并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理。由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下我们希望一致地处理它们,因为对于这些对象的区别对待将会使得程序非常复杂。组合模式为解决此类问题而诞生,它可以让叶子对象和容器对象的使用具有一致性。
其实就是一个树状结构的实现看图就知道了:

2.组合模式的实现方式

例子: 在Sunny软件公司的内部办公系统Sunny OA系统中,有一个与公司组织结构对应的树形菜单,行政人员可以给各级单位下发通知,这些单位可以是总公司的一个部门,也可以是一个分公司,还可以是分公司的一个部门。用户只需要选择一个根节点即可实现通知的下发操作,而无须关心具体的实现细节。
分析: 也就是说:公司是基础容器,部门是叶子节点
实现方式: 1.透明模式
         2.安全模式

1).透明模式

TransparentMode.java
package cn.limbo.design_patterns.composite.transparent_mode;

/**
 * 透明组合模式下的基础容器定义
 * 定义为抽象类的原因是为了提供一些缺省的方法实现
 * Created by limbo on 2016/12/2.
 */
public abstract class TransparentMode {

    //添加
    public void add(TransparentMode transparentMode) {
        System.out.println("对不起,不支持该方法...");
    }

    //移除
    public void remove(TransparentMode transparentMode) {
        System.out.println("对不起,不支持该方法...");
    }

    public TransparentMode getChild(int i) {
        System.out.println("对不起,不支持该方法...");
        return null;
    }

    public abstract void infrom();

}
TransparentCompany.java
package cn.limbo.design_patterns.composite.transparent_mode;

import java.util.ArrayList;

/**
 * 透明模式的公司类,用作基础容器进行使用
 * Created by limbo on 2016/12/2.
 */
public class TransparentCompany extends TransparentMode {

    private String companyName;

    //用于存储TransparentMode对象
    private ArrayList<TransparentMode> departments = new ArrayList<>();

    public TransparentCompany(String companyName) {
        this.companyName = companyName;
    }

    //修改缺省方法实现
    @Override
    public void add(TransparentMode transparentMode) {
        this.departments.add(transparentMode);
    }

    @Override
    public void remove(TransparentMode transparentMode) {
        this.departments.remove(transparentMode);
    }

    @Override
    public TransparentMode getChild(int i) {
        return this.departments.get(i);
    }

    //自定义通知行为,这里只是普通业务类的一个代表
    @Override
    public void infrom() {
        System.out.println(this.companyName + "正在往下属部门分发通知...");

        for (TransparentMode tmp : this.departments) {
            tmp.infrom();
        }
    }
}
TransparentDepartment.java

package cn.limbo.design_patterns.composite.transparent_mode;

/**
 * 透明模式的部门类,也就是组合设计模式中的叶子节点
 * Created by limbo on 2016/12/2.
 */
public class TransparentDepartment extends TransparentMode {

    private String departmentName;

    public TransparentDepartment(String departmentName) {
        this.departmentName = departmentName;
    }

    //发送通知
    @Override
    public void infrom() {
        System.out.println(this.departmentName + "正在给员工发送通知...");
    }
}

2).安全模式

SecurityMode.java
package cn.limbo.design_patterns.composite.security_mode;

/**
 * 安全组合模式的基础容器的实现模式
 * 个人认为使用接口实现更加好一点,因为不需要提供默认的方法实现,只要实现了容器标准就可以
 * Created by limbo on 2016/12/2.
 */
public interface SecurityMode {

    public void inform();

}
SecurityCompany.java

package cn.limbo.design_patterns.composite.security_mode;

import java.util.ArrayList;

/**
 * 安全模式公司类
 * Created by limbo on 2016/12/2.
 */
public class SecurityCompany implements SecurityMode {

    private String companyName;

    //公司下属的分公司或者是部门
    private ArrayList<SecurityMode> departments = new ArrayList<>();

    public SecurityCompany(String companyName) {
        this.companyName = companyName;
    }


    //添加
    public void add(SecurityMode securityMode) {
        this.departments.add(securityMode);
    }

    //移除
    public void remove(SecurityMode securityMode) {
        this.departments.remove(securityMode);
    }

    //获取子元素
    public SecurityMode getChild(int i) {
        return this.departments.get(i);
    }

    //自定义通知行为,这里只是普通业务类的一个代表
    @Override
    public void inform() {
        System.out.println(this.companyName + "正在往下属部门分发通知...");
        for (SecurityMode tmp : this.departments) {
            tmp.inform();
        }
    }


}

SecurityDepartment.java
package cn.limbo.design_patterns.composite.security_mode;

/**
 * Created by limbo on 2016/12/2.
 */
public class SecurityDepartment implements SecurityMode {

    private String departmentName;

    public SecurityDepartment(String departmentName) {
        this.departmentName = departmentName;
    }

    @Override
    public void inform() {
        System.out.println(this.departmentName + "正在给员工发送通知...");
    }
}

测试类:
package cn.limbo.test;

import cn.limbo.design_patterns.composite.security_mode.SecurityCompany;
import cn.limbo.design_patterns.composite.security_mode.SecurityDepartment;
import cn.limbo.design_patterns.composite.transparent_mode.TransparentCompany;
import cn.limbo.design_patterns.composite.transparent_mode.TransparentDepartment;
import cn.limbo.design_patterns.composite.transparent_mode.TransparentMode;
import org.junit.Test;

/**
 * 组合模式测试类
 * Created by limbo on 2016/12/2.
 */
public class CompositeTest {

    @Test
    public void show(){

//        transparentModeTest();
        securityModeTest();

    }

    private static void transparentModeTest(){
        TransparentMode mainCompany = new TransparentCompany("总公司");
        TransparentMode subCompany_0 = new TransparentCompany("子公司-0");
        TransparentMode subCompany_1 = new TransparentCompany("子公司-1");

        TransparentMode department_0 = new TransparentDepartment("A部门");
        TransparentMode department_1 = new TransparentDepartment("B部门");
        TransparentMode department_2 = new TransparentDepartment("C部门");
        TransparentMode department_3 = new TransparentDepartment("D部门");
        TransparentMode department_4 = new TransparentDepartment("E部门");

        mainCompany.add(subCompany_0);
        mainCompany.add(subCompany_1);

        subCompany_0.add(department_0);
        subCompany_0.add(department_1);
        subCompany_1.add(department_2);
        subCompany_1.add(department_3);
        subCompany_1.add(department_4);

        mainCompany.infrom();
    }

    private static void securityModeTest(){
        SecurityCompany mainCompany = new SecurityCompany("总公司");
        SecurityCompany subCompany_0 = new SecurityCompany("子公司-0");
        SecurityCompany subCompany_1 = new SecurityCompany("子公司-1");

        SecurityDepartment department_0 = new SecurityDepartment("A部门");
        SecurityDepartment department_1 = new SecurityDepartment("B部门");
        SecurityDepartment department_2 = new SecurityDepartment("C部门");
        SecurityDepartment department_3 = new SecurityDepartment("D部门");
        SecurityDepartment department_4 = new SecurityDepartment("E部门");

        mainCompany.add(subCompany_0);
        mainCompany.add(subCompany_1);

        subCompany_0.add(department_0);
        subCompany_0.add(department_1);
        subCompany_1.add(department_2);
        subCompany_1.add(department_3);
        subCompany_1.add(department_4);

        mainCompany.inform();
    }

}


3.优点与缺点

优点:

组合模式的主要优点如下:

(1) 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。

(2) 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。

(3) 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。

(4) 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

缺点:

在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。

4.适用场景

在以下情况下可以考虑使用组合模式:

(1) 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。

(2) 在一个使用面向对象语言开发的系统中需要处理一个树形结构。

+

(3) 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值