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

来源:互联网 发布:淘宝图片实拍保护网址 编辑:程序博客网 时间:2024/05/16 01:01

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) 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。


0 0
原创粉丝点击