组合模式(Composite)

基本理解

  • 整体和部分可以一直对待。
  • 组合模式:将对象组合成树形结构以表示“部分--整体”的层次结构。组合模式使得用户对单个对象和组合独享的使用具有一致性。
  • 透明方式和安全方式
    • 透明方式:在Component(为组合中的对象声明接口)中声明所有用来管理子对象的方法 。这样实现该接口的子类都具有了该接口中的方法。这样的好处就是叶节点和枝节点对于外界没有区别,他们具有完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备添加删除方法的功能,所以实现它是没有意义的。
    • 安全模式:在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端调用需要做相应的判断,带来了不便。

何时使用组合模式

当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以护绿组合对象昂与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

自定义控件时,就是把一些基本的控件组合起来,通过编程写成一个定制的控件。这就是典型的组合模式应用。

组合模式的好处

  • 组合模式定义了包含基本对象和组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这些组合对象又可以被组合,这样不断地递归下去,客户端代码中,任何用的的基本对象的地方都可以使用组合对象了。
  • 组合模式让客户可以一致地使用组合结构和单个对象。

何时使用组合模式

  • 想获得对象抽象的树形表示(整体部分的层次结构)。
  • 想让客户端统一处理组合结构中的所有对象。

在Cocoa Touch框架中使用组合模式

在Cocoa Touch 框架中,UIView被组织成一个组合结构。每个UIView的实例可以包含UIView的其他实例,形成统一的树形结构。让客户端对单个UIView对象和UIView的组合统一对待。

例子

首先,我们先建一个ComComponents类

ComComPonents.h

//
// ComComponents.h
// CompositeDemo
//公共的接口
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import <Foundation/Foundation.h> @interface ComComponents : NSObject
{
NSString *name;
}
//@property(nonatomic,strong)NSString *name;
- (ComComponents *)MyInit:(NSString *)myName;
- (void)Add:(ComComponents *)c;
- (void)Remove:(ComComponents *)c;
-(void)Display:(int)depth;
@end

ComComponents.m

//
// ComComponents.m
// CompositeDemo
//类接口
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "ComComponents.h" @implementation ComComponents -(ComComponents *)MyInit:(NSString *)myName {
name = myName;
return self;
} -(void)Add:(ComComponents *)c {
return;
}
-(void)Remove:(ComComponents *)c {
return;
}
-(void)Display:(int)depth {
return;
}
@end

Leaf.h

//
// Leaf.h
// CompositeDemo
//叶子类
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "ComComponents.h" @interface Leaf : ComComponents - (Leaf *)MyInit:(NSString *)myName;
@end

Leaf.m

//
// Leaf.m
// CompositeDemo
//
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "Leaf.h" @implementation Leaf -(Leaf *)MyInit:(NSString *)myName {
name = myName;
return self;
}
-(void)Add:(ComComponents *)c {
NSLog(@"Can not add a leaf");
}
-(void)Remove:(ComComponents *)c {
NSLog(@"Can not remove from a leaf");
}
-(void)Display:(int)depth {
NSLog(@"[%dLevel]%@",depth,name);
}
@end

Composite.h

//
// Composite.h
// CompositeDemo
//整体组合类
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "ComComponents.h" @interface Composite : ComComponents
{
NSMutableArray *childrenArr;
}
- (Composite *)MyInit:(NSString *)myName; @end

Composite.m

//
// Composite.m
// CompositeDemo
//
// Created by zhanggui on 15/8/6.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "Composite.h" @implementation Composite -(Composite *)MyInit:(NSString *)myName {
name = myName;
childrenArr = [NSMutableArray new];
return self;
} - (void)Add:(ComComponents *)c {
[childrenArr addObject:c];
}
- (void)Remove:(ComComponents *)c {
[childrenArr removeObject:c];
}
-(void)Display:(int)depth {
NSLog(@"[%dLevel]%@",depth,name);
for(ComComponents *component in childrenArr) {
[component Display:depth+1];
}
}
@end

然后在viewDidLoad中

- (void)viewDidLoad {
[super viewDidLoad];
Composite *root = [[Composite alloc] MyInit:@"root"];
[root Add:[[Leaf alloc] MyInit:@"Leaf A"]];
[root Add:[[Leaf alloc] MyInit:@"Leaf B"]]; Composite *comp = [[Composite alloc] MyInit:@"Composite X"];
[comp Add:[[Leaf alloc]MyInit:@"Leaf XA"]];
[comp Add:[[Leaf alloc]MyInit:@"Leaf XB"]];
[root Add:comp]; Composite *comp2 = [[Composite alloc] MyInit:@"Composite XY"];
[comp2 Add:[[Leaf alloc] MyInit:@"Leaf XYA"]];
[comp2 Add:[[Leaf alloc] MyInit:@"Leaf XYB"]];
[comp Add:comp2]; [root Add:[[Leaf alloc] MyInit:@"Leaf C"]];
Leaf *leaf = [[Leaf alloc] MyInit:@"Leaf D"]; [root Add:leaf];
[root Remove:leaf];
[root Display:1];
}

输出结果:

2015-08-06 08:45:45.520 CompositeDemo[711:156155] [1Level]root
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [2Level]Leaf A
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [2Level]Leaf B
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [2Level]Composite X
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [3Level]Leaf XA
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [3Level]Leaf XB
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [3Level]Composite XY
2015-08-06 08:45:45.520 CompositeDemo[711:156155] [4Level]Leaf XYA
2015-08-06 08:45:45.521 CompositeDemo[711:156155] [4Level]Leaf XYB
2015-08-06 08:45:45.521 CompositeDemo[711:156155] [2Level]Leaf C

我们可以看出:该例子总共有三个类包括一个接口类ComComponents和两个接口类的子类,这样的话,我们可以直接再两个子类(Leaf和Composite)中去使用接口类中定义的方法,而且也可以重写方法。从而达到了组合(Composite)和单个对象(Leaf)的一致性。

总结

组合模式的主要意图是让树形结构中的每个节点具有相同的抽象接口。这样整个结构可以作为一个统一的抽象结构使用,而不是暴露其内部表示。对每个结点的任何操作,可以通过协议或抽象基类中定义的相同接口来进行

附:

iOS设计模式之组合模式的更多相关文章

  1. C#设计模式(10)——组合模式(Composite Pattern)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  2. iOS 设计模式之工厂模式

    iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...

  3. c++设计模式15 --组合模式

    今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...

  4. 乐在其中设计模式(C#) - 组合模式(Composite Pattern)

    原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...

  5. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  6. C#设计模式(10)——组合模式(Composite Pattern)(转)

    一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...

  7. C#设计模式:组合模式(Composite Pattern)

    一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ...

  8. 【GOF23设计模式】组合模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_组合模式.树状结构.杀毒软件架构.JUnite底层架构.常见开发场景 package com.test.composite ...

  9. 设计模式:组合模式(Composite)

    定   义:将对象组合树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象使用具有一致性. 结构图: Component类: abstract class Component ...

随机推荐

  1. 你需要知道的Sass插值

    你也许会不时地写写 Sass 玩玩,你也会很享受它带给你各种便利.但还有一件事,你并不一定完全了解:插值 (interpolation) - 将一个占位符,替换成一个值.好了,你们都很幸运,因为今天我 ...

  2. 斐波那契堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了斐波那契堆,本章给出斐波那契堆的Java版本.还是那句老话,三种实现的原理一样,择其一了解即可. 目录1. 斐波那契堆的介绍2. 斐波那契堆的基本操作3. 斐波那契堆 ...

  3. 【分布式】RPC初探

    事先声明:本文代码参考自Dubbo作者的博客. RPC(Remote Procedure Call)远程过程调用,是分布式系统当中必不可少的一个玩意.比如说在单机系统当中,我想调用某个方法,直接调就可 ...

  4. Koa – 更加强大的下一代 Node.js Web 框架

    Koa 是 Express 的开发团队设计的下一代 Web 框架,其目的是为 Web 应用程序提供更小,更具表现力,更坚实的基础.Koa 没有核捆绑任何中间件,并提供了一​​套优雅的方法,使服务器端开 ...

  5. [linux]执行pip安装的程序:command not found

    执行pip安装的程序:command not found 问题描述: 我有一台阿里云服务器,上面装的是centos系统,我用pip安装好vituralenv,都没办法直接启动.同样 我今天在部署我的t ...

  6. Spring基础—— Bean 的作用域

    一.在 Spring Config 文件中,在 <bean> 元素的 scope 属性里设置 Bean 的作用域.默认为 singleton ,单例的. 二.在不引入 spring-web ...

  7. Winform开发框架之权限管理系统改进的经验总结(2)-用户选择界面的设计

    在上篇总结随笔<Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用>介绍了权限管理模块的用户管理部分,其中主要介绍了其中的用户所属公司 ...

  8. 人民币大写金额转换C#方法

    方法的代码如下: /// <summary> /// 人民币大写 /// </summary> /// <param name="input"> ...

  9. php Calender(日历)代码

    代码如下: <?php /** * * 我的日历 * date_default_timezone_set date mktime * @param int $year * @param int ...

  10. macbook 我们需要买吗

    能否写出好代码与是否使用“好”的电脑是没有直接关系的.