设计模式-组合模式

介绍

  该模式的目的是系统对单个对象和多个对象的使用,具有一致性。比如我们的电脑上,有文件和文件夹(多个对象),新增、删除、修改它们用相同的操作,还有像树形菜单。这样客户端无需辨别到底是单个对象还是多个对象,可以直接操作,给客户带来便利。

角色定义

  抽象节点角色:通常是一个抽象类,声明以下2个角色的公共行为操作
  树枝节点角色:继承抽象节点角色,实现抽象节点声明的方法。该角色会存储子元素(叶子节点或树枝节点),通常有add()、remove()、getChild()方法来管理子元素
  叶子节点角色:继承抽象节点角色,该角色作为存储单元的最下层,没有子元素

模式

  组合模式还细分为:透明模式和安全模式。
  透明模式:抽象节点角色拥有树枝节点角色和叶子节点角色的所有方法,包含管理子元素的相关方法:add()、remove()、getChild()等(这些方法可以是空处理或者报异常)
  安全模式:抽象节点角色只拥有树枝节点角色、叶子节点角色的共有方法,不包含管理子元素的相关方法,只有树枝节点角色有add()、remove()、getChild()等方法

代码示例

  透明模式
	/**
	 * 抽象节点角色
	 */
	public abstract class Root {
	
	    protected String name;
	
	    public Root(String name) {
	        this.name = name;
	    }
	
	    public abstract String operation();
	
	    public boolean addChild(Root root) {
	        throw new 
	        UnsupportedOperationException("addChild not supported!");
	    }
	
	    public boolean removeChild(Root root) {
	        throw new 
	        UnsupportedOperationException("removeChild not supported!");
	    }
	
	    public Root getChild(int index) {
	        throw new 
	        UnsupportedOperationException("getChild not supported!");
	    }
	
	}
	
	
	/**
	 * 树枝节点角色
	 */
	public class Branch extends Root {
	
	    private List<Root> leafList;
	
	    public Branch(String name) {
	        super(name);
	        this.leafList = new ArrayList<>();
	    }
	
	    @Override
	    public String operation() {
	        StringBuilder builder = new StringBuilder(this.name);
	        for (Root leaf : this.leafList) {
	            builder.append(System.getProperty("line.separator"));
	            builder.append(leaf.operation());
	        }
	        return builder.toString();
	    }
	
	    @Override
	    public boolean addChild(Root root) {
	        return this.leafList.add(root);
	    }
	
	    @Override
	    public boolean removeChild(Root root) {
	        return this.leafList.remove(root);
	    }
	
	    @Override
	    public Root getChild(int index) {
	        return this.leafList.get(index);
	    }
	
	}
	
	
	/**
	 * 叶子节点角色
	 */
	public class Leaf extends Root {
	
	    public Leaf(String name) {
	        super(name);
	    }
	
	    @Override
	    public String operation() {
	        return this.name;
	    }
	
	}
	
	
	/**
	 * 测试类
	 */
	public class Test {
	    public static void main(String[] args) {
	        Root root = new Branch("root");
	
	        Root branchA = new Branch("--branchA");
	        Root leafA = new Leaf("--leafA");
	
	        Root leafB = new Leaf("----leafB");
	        Root branchB = new Branch("----branchB");
	
	        Root leafC = new Leaf("------leafC");
	
	        root.addChild(branchA);
	        root.addChild(leafA);
	        branchA.addChild(leafB);
	        branchA.addChild(branchB);
	        branchB.addChild(leafC);
	
	        String result = root.operation();
	        System.out.println(result);
	    }
	}

  运行结果:

在这里插入图片描述

  安全模式
	/**
	 * 抽象节点角色
	 */
	public abstract class Root {
	
	    protected String name;
	
	    public Root(String name) {
	        this.name = name;
	    }
	
	    public abstract String operation();
	
	}
	
	
	// 树枝节点角色那几个方法去除@Override,叶子节点角色代码不动
	/**
	 * 测试类
	 */
	public class Test {
	
	    public static void main(String[] args) {
	        Branch root = new Branch("root");
	
	        Branch branchA = new Branch("--branchA");
	        Root leafA = new Leaf("--leafA");
	
	        Root leafB = new Leaf("----leafB");
	        Branch branchB = new Branch("----branchB");
	
	        Root leafC = new Leaf("------leafC");
	
	        root.addChild(branchA);
	        root.addChild(leafA);
	        branchA.addChild(leafB);
	        branchA.addChild(branchB);
	        branchB.addChild(leafC);
	
	        String result = root.operation();
	        System.out.println(result);
	    }
	
	}

  运行结果同上,不过客户端要区分树枝节点角色和叶子节点角色,不然无法调用管理子元素的方法。

优缺点

  优点:

  • 简化了客户端的代码,无需区分是单个对象还是组合对象
  • 组合对象自由添加新对象后,对它的操作是不用变动的

  缺点:

  • 如果组合对象层次多,客户端需要花较多时间理清内部的层次关系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值