求知 文章 文库 Lib 视频 iProcess 课程 角色 咨询 工具 讲座 Modeler   Code  
会员   
 
  
每天15篇文章
不仅获得谋生技能
更可以追随信仰
 
 
 
组合模式(Composite)的安全模式与透明模式

2010-10-11 作者:haolloyin 来源:haolloyin的blog

 

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

使用场景:

1、用于对象的部分-整体层次结构,如树形菜单、文件夹菜单、部门组织架构图等;

2、对用户隐藏组合对象与单个对象的不同,使得用户统一地使用组合结构中的所有对象。

通用类图:

说到树,“数据结构”这门课上都学习过了,树的遍历问题最重要了。下面按照类图直接用简单的代码实现一番。

// 抽象构件类、节点类
abstract class Component {
	public String name;

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

	// 公有操作
	public void getName() {
		System.out.println(this.name);
	}
}

// 树枝构件类
class Composite extends Component {

	private LinkedList<Component> children;

	public Composite(String name) {
		super(name);
		this.children = new LinkedList<Component>();
	}

	// 添加一个节点,可能是树枝、叶子
	public void add(Component child) {
		this.children.add(child);
	}

	// 删除一个节点,可能是树枝、叶子
	public void remove(String child) {
		this.children.remove(child);
	}

	// 获取子树
	public LinkedList<Component> getChildren() {
		return this.children;
	}
}

// 树叶构件类
class Leaf extends Component {

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

 

// 测试类,负责构建整棵树
public class Client {
	public static void main(String[] args) {

		Composite root = new Composite("树根");

		Composite branch01 = new Composite("树枝01");
		Composite branch02 = new Composite("树枝02");

		root.add(branch01);
		root.add(branch02);

		Component leaf01 = new Leaf("树叶01");
		Component leaf02 = new Leaf("树叶02");
		Component leaf03 = new Leaf("树叶03");
		Component leaf04 = new Leaf("树叶04");
		Component leaf05 = new Leaf("树叶05");

		branch01.add(leaf01);
		branch01.add(leaf02);

		branch02.add(leaf03);
		branch02.add(leaf04);
		branch02.add(leaf05);
		
		displayTree(root);

	}

	// 递归遍历整棵树
	public static void displayTree(Composite root) {
		LinkedList<Component> children = root.getChildren();

		for (Component c : children) {
			if (c instanceof Leaf) {
				System.out.print("\t");
				c.getName();
			} else {
				c.getName();
				// 递归
				displayTree((Composite)c);
			}
		}
	}
}

测试结果:

树枝01
	树叶01
	树叶02
树枝02
	树叶03
	树叶04
	树叶05

上面的 Client 类构建树的代码让人看了觉得烦,如果整棵树下来有几百个节点,这样子的工作效率太糟糕了。其实,在实际应用中,并不是这样子手工地构建一棵复杂的树的,应该是我们已经将整棵树的节点内容、逻辑关系都存储在数据库表中(更重要的是这录入工作应该不是我们开发人员做的),由于表中的各个节点记录都保存有自身的一些相关信息,包括是否为树叶、父节点等等,开发人员需要的就是让程序从数据库中的表中读取记录来构建整棵树。

此外,上面的代码中只能从根节点往下遍历,不能够从某一节点开始往上遍历,解决这个问题可以在抽象构件类 Component 类中添加一个 parent 属性,再添加相应 setParent() 、 getParent()方法即可。而关于不同的遍历方法再具体实现一下就完成了。

上面的类图是属于安全模式的,因为 Leaf 类不具有 add 、 remove 等方法,这些具体方法是被下置到 Composite 类(树枝节点类)中去具体实现了。

如果要实现透明模式,类图如下:

差别仅在于将 add 、remove 等方法上升到抽象构件类 Component 中去了。那么此时 Leaf 类在具体实现时就必须将继承而来的 add 、remove 等不可用、不合逻辑的方法给注解 Deprecated 掉,并抛出适当的异常,不提供给用户使用。看起来这种透明模式似乎更加麻烦,没事找事。其实,这种模式下使得我们在遍历整棵树的时候可以不进行强制类型转换。看看上面的 displayTree() 方法,里面在使用递归遍历时就使用到了 (Composite)c 强制类型转换了。

Leaf 类代码如下:

// 树叶构件类
class Leaf extends Component {

	public Leaf(String name) {
		super(name);
	}
	
	@Deprecated // 抛出不支持的操作异常
	public void add(Component child) throws UnsupportedOperationException{
		throws new UnsupportedOperationException();
	}

	@Deprecated
	public void remove(String child) throws UnsupportedOperationException{
		throws new UnsupportedOperationException();
	}

	@Deprecated
	public LinkedList<Component> getChildren() throws UnsupportedOperationException{
		throws new UnsupportedOperationException();
	}
}

具体怎么使用安全模式或透明模式,看具体情况咯。

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://haolloyin.blog.51cto.com/1177454/347308



如何向妻子解释OOD
OOAD与UML笔记
UML类图与类的关系详解
UML统一建模语言初学
总结一下领域模型的验证
基于 UML 的业务建模


面向对象的分析设计
基于UML的面向对象分析设计
UML + 嵌入式系统分析设计
关系数据库面向OOAD设计
业务建模与业务架构
使用用例进行需求管理


某航空IT部门 业务分析与业务建模
联想 业务需求分析与建模
北京航管科技 EA工具与架构设计
使用EA和UML进行嵌入式系统分析
全球最大的茶业集团 UML系统分析
华为 基于EA的嵌入式系统建模
水资源服务商 基于EA进行UML建模
更多...   
 
 
 
 
 
每天2个文档/视频
扫描微信二维码订阅
订阅技术月刊
获得每月300个技术资源
 
 

关于我们 | 联系我们 | 京ICP备10020922号 京公海网安备110108001071号