设计模式之组合模式

组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。


需求:公司管理系统的设计,公司有多个部门,总公司又含有子公司。


示例

定义公司对象的抽象父类,定义具体的职责:

public abstract class Company {

protected String name;

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

//增加公司
public abstract void add(Company company);

//移除公司
public abstract void remove(Company company);

//显示
public abstract void display(int depth);

//部门履行的职责
public abstract void lineOfDuty();
}

公司的实现类:

public class ConcreteCompany extends Company {

public List<Company> chldren = new ArrayList<>();

public ConcreteCompany(String name) {
    super(name);
}

@Override
public void add(Company company) {

    chldren.add(company);
}

@Override
public void remove(Company company) {

    chldren.remove(company);
}

@Override
public void display(int depth) {

    StringBuilder sb =new StringBuilder(depth);
    for (int i = 0; i < depth; i++) {
        sb.append("-");
    }
    System.out.println(sb+ name);

    for (Company c : chldren
            ) {
        c.display(depth + 2);
    }
}

@Override
public void lineOfDuty() {
    for (Company c : chldren
            ) {
        c.lineOfDuty();
    }
}
}

定义公司的部门–人事部

public class HRDepartment extends Company {
public HRDepartment(String name) {
    super(name);
}

@Override
public void add(Company company) {

}

@Override
public void remove(Company company) {

}

@Override
public void display(int depth) {
    StringBuilder sb = new StringBuilder(depth);
    for (int i = 0; i < depth; i++) {
        sb.append("-");
    }
    System.out.println(sb + name);

}

@Override
public void lineOfDuty() {

    System.out.println(name + "人事管理");
}
}

再来一个财务部

public class FinanceDepartment extends Company {
public FinanceDepartment(String name) {
    super(name);
}

@Override
public void add(Company company) {

}

@Override
public void remove(Company company) {

}

@Override
public void display(int depth) {
    StringBuilder sb = new StringBuilder(depth);
    for (int i = 0; i < depth; i++) {
        sb.append("-");
    }
    System.out.println(sb + name);
}

@Override
public void lineOfDuty() {
    System.out.println(name + "财务管理");
}
}

到此,我们就可以创建一个公司,而且公司里可以有财务部和人事部了;运行测试:

 public void compositeTest() {

    ConcreteCompany root = new ConcreteCompany("北京总公司");
    root.add(new HRDepartment("总公司人事部"));
    root.add(new FinanceDepartment("总公司财务部"));

    ConcreteCompany sh = new ConcreteCompany("上海分公司");
    sh.add(new HRDepartment("上海分公司人事部"));
    sh.add(new FinanceDepartment("上海分公司财务部"));
    root.add(sh);

    ConcreteCompany nj = new ConcreteCompany("南京分公司");
    nj.add(new HRDepartment("南京分公司人事部"));
    nj.add(new FinanceDepartment("南京分公司财务部"));
    root.add(nj);

    ConcreteCompany hk = new ConcreteCompany("香港分公司");
    hk.add(new HRDepartment("香港分公司人事部"));
    hk.add(new FinanceDepartment("香港分公司财务部"));
    root.add(hk);

    root.display(1);
    root.lineOfDuty();

}
  运行结果:
  -北京总公司
    ---总公司人事部
    ---总公司财务部
    ---上海分公司
    -----上海分公司人事部
    -----上海分公司财务部
    ---南京分公司
    -----南京分公司人事部
    -----南京分公司财务部
    ---香港分公司
    -----香港分公司人事部
    -----香港分公司财务部
    总公司人事部人事管理
    总公司财务部财务管理
    上海分公司人事部人事管理
    上海分公司财务部财务管理
    南京分公司人事部人事管理
    南京分公司财务部财务管理
    香港分公司人事部人事管理
    香港分公司财务部财务管理

如果我们需要新增一个子公司或者是部门,只需要声明相关的对象即可。

透明方式与安全方式

上面的实现方式为透明方式:

也就是说在Component(Company)中声明所有来管理子对象的方法,其中包括add,remove等。这样实现的Component接口的所有子类都具备了add和remove。这样做的好处就是叶节点和枝节点对于外界没有区别,他们具备完全一致的行为接口。但问题也很明显,因为叶节点本身不具备ADD(),REMOVE()方法的功能,所以实现它是没有意义的。

安全方式:在Component中不去声明add和remove方法,那么子类的叶节点就不需要去实现它,而在Composite声明所有来管理子类对象的方法。不过由于不够透明,所有树叶和树枝类将不具备相同的接口,客户端的调用需要做相应的判断,带来了不便。


何时使用组合模式:当发现需求中是体现部分与整体层次的结构是,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑组合模式了。

例子来源及参考资料:《大话设计模式》

源码地址

本文地址:http://blog.csdn.net/ProdigalWang/article/details/78212030

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值