被说了很多遍的设计模式---组合模式

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍组合模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

文件系统的目录结构,公司或政府部门的组织结构等具有树形递归关系的抽象组织结构。

思路分析:

要点一:每一级都可作为一个完整的最小树型结构。

要点二:每一级的外在表现类似,具有屏蔽层次结构的功能。如:文件系统不同级别的目录都具有相同的表现形式。分级行政办公组织结构中的相同部门设置。

要点三:对软件实现而言,需要尽可能的提高代码复用度。

示例工程:


组合模式模板代码【本例我们先展示模板代码,稍后演示一个具体的示例】


创建Component.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;

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);
}
创建Composite.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;

import java.util.ArrayList;
import java.util.List;
public class Composite extends Component {
	private List<Component> children = new ArrayList<Component>();
	
	public Composite(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@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("-"+name);
		for(Component c:children){
			c.display(depth+1);
		}
	}
}
创建Leaf.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;

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 leaf");
	}

	@Override
	public void remove(Component c) {
		System.out.println("cannot remove from a leaf");
	}

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		System.out.println(new String("----")+"depth:"+depth+"name:"+name);
	}
}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;

public class Window {
	public static void main(String[] args) {
		Composite root = new Composite("root");
		root.add(new Leaf("Leaf A"));
		root.add(new Leaf("Leaf B"));
		
		Composite comp = new Composite("ComposteX");
		comp.add(new Leaf("Leaf XA"));
		comp.add(new Leaf("Leaf XB"));
		root.add(comp);
		
		Composite comp2 = new Composite("ComposteXY");
		comp2.add(new Leaf("Leaf XYA"));
		comp2.add(new Leaf("Leaf XYB"));
		comp.add(comp2);
		root.add(new Leaf("Leaf C"));
		
		Leaf l = new Leaf("Leaf D");
		root.add(l);
		root.remove(l);
		root.display(1);
	}
}

【上面的代码直接看的话,可能有难度。先把代码提供给各位看官是希望现将代码运行起来,观察结果。下面我们介绍相关的概念与原理】

模式总结:

组合模式结构图:


组合模式:

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

组成部分:

Component:抽象构件。可以是接口或者抽象类。其中包含leaf与composite公共接口的声明。如,增删改功能。

Leaf:叶子节点。其实就是最后一级节点,其下不能再有任何形式的impl或extend关系。其本身必须实现Component中定义的内容。

Composite:容器组件。是相对于Leaf定义的。其下还能够挂载其他的节点(可以是Leaf或Composite)。其中,可以通过递归实现对子部件的调用。

【以上,可以类比文件系统中的文件夹,文件夹可以包含文件或文件夹,文件本身不能包含其他文件或文件夹】

特别提示:上面的模板代码,在leaf与Composite中都包含了add和remove方法。但事实上,只有Composite的中的方法才是有效的。

实际场景用例:

需求描述:

公司包括:子公司,人力,研发,财务。子公司包括:子公司(可选的),人力,研发,财务。等等。

示例代码:


创建Company.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;

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();
}
创建ConcreteCompany.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;

import java.util.ArrayList;
import java.util.List;

public class ConcreteCompany extends Company {
	private List<Company> children = new ArrayList<Company>();
	
	public ConcreteCompany(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@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("-"+name);
		for(Company c:children){
			c.display(depth);
		}
	}

	@Override
	public void lineOfDuty() {
		// TODO Auto-generated method stub
		for(Company c:children){
			c.lineOfDuty();
		}
	}
}
创建FinanceDepartment.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;

public class FinanceDepartment extends Company{

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

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		
	}

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

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		System.out.println("----"+name);
	}

	@Override
	public void lineOfDuty() {
		// TODO Auto-generated method stub
		System.out.println("finance duty:"+name);
	}
}
创建HRDepartment.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;

public class HRDepartment extends Company{

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

	@Override
	public void add(Company c) {
		// TODO Auto-generated method stub
		
	}

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

	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		System.out.println("----"+name);
	}

	@Override
	public void lineOfDuty() {
		// TODO Auto-generated method stub
		System.out.println("HR duty:"+name);
	}
}

创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;


public class Window {
	public static void main(String[] args) {;
		Company root = new ConcreteCompany("总公司");
		root.add(new HRDepartment("总公司人力资源部"));
		root.add(new FinanceDepartment("总公司财务部"));

		ConcreteCompany comp1 = new ConcreteCompany("上海分公司");
		comp1.add(new HRDepartment("上海分公司人力资源部"));
		comp1.add(new FinanceDepartment("上海分公司财务部"));
		root.add(comp1);
		
		ConcreteCompany comp2 = new ConcreteCompany("南京分公司");
		comp2.add(new HRDepartment("南京分公司人力资源部"));
		comp2.add(new FinanceDepartment("南京分公司财务部"));
		root.add(comp2);
		
		root.display(1);
		root.lineOfDuty();

	}
}

注:与模板代码对比,这里root对象也可以是抽象类Company。但,具体组织需要特别声明为具体实现。

模式扩展:

在上文中,我们说只有composite中的add和remove是有效的。

事实上,这些方法的设置在组合模式中成为透明组合模式,安全组合模式。即,在透明组合模式中,这些方法不区分leaf与composite。具体应用时可以通过返回值的变化或异常信息返回。而,安全组合模式要求父类不提供该方法的声明,而是由composite进行声明,这样在Window主类中就需要区别声明leaf与composite两个对象。

反思:

应用场景:

  1. 具有整体与部分的树形层次结构关系时,希望通过相同的结构屏蔽层次之间的差异性。
  2. 不同树形层次的功能具有类似性,并且希望达到重用的目的。
  3. 层次关系是不固定的,需要按照需求修改。

优点:

  1. 组合模式能够清楚的定义出复杂的关系。并且向客户端屏蔽了这种复杂与差异性。
  2. 客户端使用树形结构中的任何一个关系,可以通过一个统一的接口。有效减少客户端的依赖程度。
  3. 对树形结构的调整非常方便。而树形结构本身可能是非常复杂的。

缺点:

  1. 对于树形层次的约束不够。如,在组织关系处理中,子公司内不需要设置***部,但由于没有强制的约束条件,客户端可以随意修改。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---组合模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值