设计模式之组合模式

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

组合模式抽象代码:

public abstract class Component {
    protected String name;
    public Component(String name){
        this.name = name;
    }
    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract void display(int depth);
}
public class Composite extends Component{
    private List<Component> children = new ArrayList<Component>();
    public Composite(String name){
        super(name);
    }

    @Override
    public void add(Component c) {
        // TODO Auto-generated method stub
        children.add(c);
    }

    @Override
    public void remove(Component c) {
        // TODO Auto-generated method stub
        children.remove(c);
    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(getStr(depth) + name);
        for(Component component : children){
            component.display(depth + 2);
        }
    }
    public String getStr(int depth){
        StringBuilder sb = new StringBuilder();
        for(int i =0; i < depth; i++){
            sb.append('-');
        }
        return sb.toString();
    }
}
public class Leaf extends Component{
    public Leaf(String name){
        super(name);
    }

    @Override
    public void add(Component c) {
        // TODO Auto-generated method stub
        System.out.println("cannot add to a leaf");
    }

    @Override
    public void remove(Component c) {
        // TODO Auto-generated method stub
        System.out.println("cannot remove from a leaf");
    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(getStr(depth) + name);
    }
    public String getStr(int depth){
        StringBuilder sb = new StringBuilder();
        for(int i =0; i < depth; i++){
            sb.append('-');
        }
        return sb.toString();
    }
}
public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Composite root = new Composite("root");
        root.add(new Leaf("Leaf A"));
        root.add(new Leaf("Leaf B"));
        
        Composite comp = new Composite("X");
        comp.add(new Leaf("Leaf XA"));
        comp.add(new Leaf("Leaf XB"));
        
        root.add(comp);
        
        Composite comp2 = new Composite("XY");
        comp2.add(new Leaf("Leaf XYA"));
        comp2.add(new Leaf("Leaf XYB"));
        comp.add(comp2);
        
        root.add(new Leaf("Leaf C"));
        
        Leaf leaf = new Leaf("Leaf D");
        root.add(leaf);
        root.remove(leaf);
        
        root.display(1);
    }

}

何时使用组合模式?

当发现需求中体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式了。比如分公司或办事处与总公司的关系,就是部分与整体的关系。我们希望公司的组织结构,比如人力资源部,财务部的管理功能可以复用于分公司,这其实就是部分与整体可以被一致对待的问题。我们来代码实现一下。

公司管理系统代码结构图:

public abstract class Company {
    protected String name;
    public Company(String name){
        this.name = name;
    }
    public abstract void add(Company c);
    public abstract void remove(Company c);
    public abstract void display(int depth);
    public abstract void lineOfDuty();
}
public class ConcreteCompany extends Company{
    private List<Company> children = new ArrayList<Company>();
    public ConcreteCompany(String name){
        super(name);
    }
    @Override
    public void add(Company c) {
        // TODO Auto-generated method stub
        children.add(c);
    }

    @Override
    public void remove(Company c) {
        // TODO Auto-generated method stub
        children.remove(c);
    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(getStr(depth) + name);
        for(Company company : children){
            company.display(depth + 2);
        }
    }
    public String getStr(int depth){
        StringBuilder sb = new StringBuilder();
        for(int i =0; i < depth; i++){
            sb.append('-');
        }
        return sb.toString();
    }
    @Override
    public void lineOfDuty() {
        // TODO Auto-generated method stub
        for(Company company : children){
            company.lineOfDuty();
        }
    }
}
public class FinanceDepartment extends Company{
    public FinanceDepartment(String name){
        super(name);
    }
    @Override
    public void add(Company c) {
    }

    @Override
    public void remove(Company c) {

    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(getStr(depth) + name);
    }
    public String getStr(int depth){
        StringBuilder sb = new StringBuilder();
        for(int i =0; i < depth; i++){
            sb.append('-');
        }
        return sb.toString();
    }
    @Override
    public void lineOfDuty() {
        System.out.println(name + " 公司财务收支管理");
    }
}
public class HRDepartment extends Company{
    public HRDepartment(String name){
        super(name);
    }
    @Override
    public void add(Company c) {
    }

    @Override
    public void remove(Company c) {

    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(getStr(depth) + name);
    }
    public String getStr(int depth){
        StringBuilder sb = new StringBuilder();
        for(int i =0; i < depth; i++){
            sb.append('-');
        }
        return sb.toString();
    }
    @Override
    public void lineOfDuty() {
        System.out.println(name + " 员工招聘培训管理");
    }
}
public class Test1 {
    public static void main(String[] args){
        ConcreteCompany root = new ConcreteCompany("北京总公司");
        root.add(new HRDepartment("总公司人力资源部"));
        root.add(new FinanceDepartment("总公司财务部"));
        
        ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
        comp.add(new HRDepartment("华东分公司人力资源部"));
        comp.add(new FinanceDepartment("华东分公司财务部"));
        root.add(comp);
        
        ConcreteCompany comp2 = new ConcreteCompany("南京办事处");
        comp2.add(new HRDepartment("南京办事处人力资源部"));
        comp2.add(new FinanceDepartment("南京办事处财务部"));
        comp.add(comp2);
        
        ConcreteCompany comp3 = new ConcreteCompany("杭州办事处");
        comp3.add(new HRDepartment("杭州办事处人力资源部"));
        comp3.add(new FinanceDepartment("杭州办事处财务部"));
        comp.add(comp3);
        
        root.display(1);
        System.out.println("职责-----------");
        root.lineOfDuty();
    }
}

组合模式的好处:

用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。简单点说,就是组合模式让客户可以一致地使用组合结构和单个对象。

 

posted @ 2018-07-23 11:12  Ericyshi  阅读(124)  评论(0编辑  收藏  举报