组合模式(Composite Pattern)
来源:互联网 发布:打印机无法网络打印 编辑:程序博客网 时间:2024/06/05 20:57
定义
组合模式将具有相同的基本类型的对象组合成树形结构的对象,该树的父节点和子节点具有相同的类型,相同的接口。换句话说,将对象组合成树形结构以表示“部分-整体”的层次结构,Composite使得用户对单个对象和组合对象的使用具有一致性。
由于父节点和子节点具有相同的基本类型,所以在整个树上不需要做任何类型检查,客户端就可以在父节点和子节点上进行相同的操作,而不需要区分它所需要操作的对象是父节点还是子节点。使用组合对象的客户端可以忽略树的父节点和字节点得差异,使得用起来非常顺手、简单,下面是一个运行时的组合对象结构的示例:
上述的组合对象是一个树形结构,不过并非一个二叉树,每个对象都是具有相同的接口,使得客户端看起来并无差异。类似的组合模式的静态结构类图如下图所示:
Component所定义的接口是类Leaf和Composite共享的。从上图的定义来看,显然有些接口Leaf并没有对应的意义,所以在图中的Leaf中并没有看到Component的全部接口,但是,你别以为Leaf不支持这些接口。虽然有些接口只有在Composite类里面有意义,比如上述类图中的add:Component、remove:Component等,但是这不妨碍类Leaf共享该接口,只不过类Leaf实现该方法是使用空方法而已(因为这些接口对Leaf毫无意义,只是为了和整个树保持统一而已)。
树的每个节点或表示一个叶子节点,或表示一个组合节点,他们的主要区别在于叶子节点没有组合节点的子节点。但是,因为叶子节点和组合节点共享一套接口,所以任何属于Component的操作都可以安全地适用于叶子节点和组合节点。
关于组合设计模式,其原定义如下所示:
适用场景
你如果有以下需求,不妨考虑考虑:
- 你希望客户端忽略组合对象与单个对象的不同,而是能够统一地使用组合结构中的所有对象
- 你希望表现出对象-层次的层次结构
- 通过定义包括基本对象和组合对象的层次结构,你可以使用简单的基本对象组合晨较为复杂的组合对象,而你还可以继续使用较为复杂的组合对象组合成更为复杂的对象,如此递归循环,你可以组成自己所需要的更复杂的结构对象。但是,对于客户端而言,使用简单对象和使用复杂组合对象是无差别的
- 简化客户单代码,同时使得创建同类型的复杂对象更简单。因为客户端不需要区分单个对象还是组合对象,所以不必写if-else之类的各种判断,而新对象也只需组合即可
Cocoa Touch中的组合模式
在Cocoa Touch框架中,UIViews是使用组合模式的树形结构组织管理的。每一个UIView对象都可以包含其他的UIView对象以构建一颗统一的树结构,使得客户端可以一同对待单个UIView对象和组合UIView对象。IOS程序中,window内的UIView对象是一颗内建的树形结构,其中树的根是UIWindow对象所包含的UIView对象,其他的UIView对象是它的子视图。虽然其他的是子视图,但是任何UIView对象都可以通过往该视图里面添加子视图而转变为父视图,任何UIView对象!UIView对象只能有一个父视图,但是允许有任意多个子视图。(树不就是这样?)UIView视图管理示意图如下所示:
上图的关系图可以使用更为清晰的树形示意图表示为:
组成树形结构的view对象也是事件处理和动作消息的响应链。
代码示例
//// Component.h// CompositeDemo//// Created by God Lin on 15/1/25.// Copyright (c) 2015年 arbboter. All rights reserved.//#import <Foundation/Foundation.h>@interface UDComponent : NSObject- (void) operation;- (void) add:(UDComponent*)component;- (void) remove:(UDComponent*)component;- (NSInteger) getCount;@end
//// Component.m// CompositeDemo//// Created by God Lin on 15/1/25.// Copyright (c) 2015年 arbboter. All rights reserved.//#import "Component.h"@interface UDComponent ()@property (nonatomic, strong) NSMutableArray* children;@end@implementation UDComponent- (id) init{ if(self = [super init]) { _children = [[NSMutableArray alloc] init]; } return self;}- (void) operation;{ NSLog(@"...do nothing.");}- (void) add:(UDComponent*)component{ [self.children addObject:component];}- (void) remove:(UDComponent*)component{ [self.children removeObject:component];}- (NSInteger) getCount{ NSInteger sum = 1; for (UDComponent* c in self.children) { sum += [c getCount]; } return sum;}@end这里的UDComponent定义了一些默认的方法,子类可选择是否直接使用,不过需要对应的声明变量_children.
//// Composite.m// CompositeDemo//// Created by God Lin on 15/1/25.// Copyright (c) 2015年 arbboter. All rights reserved.//#import "Composite.h"@interface Composite ()// 为了简示Composite和Component内部的不同,定义不同的属性变量// 存储子节点@property (nonatomic, strong) NSMutableArray* sons;@end// 如果这里仍然像UDComponent使用children存储子节点,// 那么这里可以直接使用父类的方法,不需要自己写// 示例为了表现出内部的复杂性@implementation Composite- (id) init{ if(self = [super init]) { _sons = [[NSMutableArray alloc] init]; } return self;}- (void) operation;{ NSLog(@"child node count -> %ld", self.sons.count); for (UDComponent* c in self.sons) { [c operation]; }}- (void) add:(UDComponent*)component{ [self.sons addObject:component];}- (void) remove:(UDComponent*)component{ [self.sons removeObject:component];}- (NSInteger) getCount{ NSInteger sum = 1; for (UDComponent* c in self.sons) { sum += [c getCount]; } return sum;}@endComposite重新自实现了一遍。
Leaf定义实现如下:
//// Leaf.m// CompositeDemo//// Created by God Lin on 15/1/25.// Copyright (c) 2015年 arbboter. All rights reserved.//#import "Leaf.h"// 无子节点,所以不需要定义存储子节点的变量@implementation Leaf- (void) operation;{ NSLog(@"leaf node, no child");}- (void) add:(UDComponent*)component{ // 该方法对Leaf无意义,空白实现}- (void) remove:(UDComponent*)component{ // 该方法对Leaf无意义,空白实现}- (NSInteger) getCount{ return 1;}@end客户端测试使用的代码如下:
//// main.m// CompositeDemo//// Created by God Lin on 15/1/23.// Copyright (c) 2015年 arbboter. All rights reserved.//#import <Foundation/Foundation.h>#import "Leaf.h"#import "Composite.h"int main(int argc, const char * argv[]){ @autoreleasepool { // 生成本章的运行时对象结构图 // 从下往上生成 Composite* composite = nil; Leaf* leaf = [[Leaf alloc] init]; composite = [[Composite alloc] init]; [composite add:leaf]; [composite add:[[Leaf alloc] init]]; [composite add:[[Leaf alloc] init]]; Composite* compositeFather = nil; compositeFather = [[Composite alloc] init]; [compositeFather add:composite]; [compositeFather add:[[Leaf alloc] init]]; composite = compositeFather; compositeFather = [[Composite alloc] init]; [compositeFather add:[[Leaf alloc] init]]; [compositeFather add:[[Leaf alloc] init]]; [compositeFather add:composite]; [compositeFather add:[[Leaf alloc] init]]; // 客户端使用组合对象 // 组合 [compositeFather operation]; // 单个对象 [leaf operation]; } return 0;}可以看到,使用组合对象不管是构建一颗有层次的树,还是客户端可以简单地使用组合对象的对象(不需要区分Composite和Leaf对象),组合模式都有非常大得优势。
总结
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern )
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式-Composite Pattern
- Composite Pattern(组合模式)
- [Array和ArrayList的区别]
- hdu1372 Knight Moves(BFS)
- scheme 矩阵运算
- C语言编程(练习8:数组与指针)
- thinkphp3.2 ajax无刷新提交post
- 组合模式(Composite Pattern)
- 解决自动部署到jboss时,设置虚拟主机的问题。
- 用MFC实现静态文本超链接的方法
- mysql 的一些操作
- js取整函数
- java设计模式-代理模式小结
- 多方位解析PHP vs Node.js之争
- BZOJ 3316 JC loves Mkk 二分答案+单调队列
- 连接数据库错误The Network Adapter could not establish the connection