iOS设计形式之组成方式,组合格局

结缘格局(Composite)

1. 何为组合形式

定义:将对象组合成树形结构以象征‘部分-全体’的等级次序结构。组合方式使得用户对单个对象和重组对象的行使全部1致性。

图片 1

图一-1 组合格局结构图

Component为组合中的对象表明接口,在得当意况下,实现全数类共有接口的暗许行为。
  Leaf在整合中代表叶节点对象,叶节点未有子节点。
  Composite定义有枝节点行为,用来存储子部件,在Component接口中落到实处与子部件有关的操作,比方扩大Add和删除Remove。

主导领悟

  • 总体和壹部分能够一向对待。
  • 重组方式:将目的组合成树形结构以代表“部分–全部”的档次结构。组合格局使得用户对单个对象和构成独享的采纳具备1致性。
  • 晶莹剔透方式和平安格局
    • 晶莹剔透情势:在Component(为组合中的对象表明接口)中扬言全体用来管理子对象的章程
      。那样完成该接口的子类都具备了该接口中的方法。那样的益处就是叶节点和枝节点对于外界未有分歧,他们全部完全1致的行事接口。但难点也很让人惊讶,因为Leaf类本人不持有丰裕删减方法的作用,所以实现它是向来不意思的。
    • 有惊无险情势:在Component接口中不去评释Add和Remove方法,那么子类的Leaf也就不供给去贯彻它,而是在Composite证明全数用来治本子类对象的格局,那样做就不会出现刚才提到的主题素材,可是出于不够透明,所以树叶和树枝类将不享有同等的接口,客户端调用须求做相应的推断,带来了不便。

贰. 情况设置

几时使用组合格局

当您发觉须求中是反映部分与总体等级次序的组织时,以及你指望用户能够保护绿化组合对象昂与单个对象的例外,统一地使用组合结构中的全体目标时,就应当考虑用整合情势了。
自定义控件时,正是把一部分中央的控件组合起来,通过编制程序写成三个定制的控件。那正是压倒元稹和白居易的组合格局应用。

3. 代码达成

(1)ComComponent

@interface ComComponent : NSObject
{
    NSString *name;
}

- (ComComponent *)initWithName:(NSString *)myName;

// 通常都用add和remove方法来提供增加或者移除树叶或树枝的功能
- (void)add:(ComComponent *)c;
- (void)remove:(ComComponent *)c;
- (void)display:(int)depth;

@end

@implementation ComComponent

- (ComComponent *)initWithName:(NSString *)myName
{
    if (self = [super init]) {
        name = myName;
    }
    return self;
}

- (void)add:(ComComponent *)c
{
    return;
}

- (void)remove:(ComComponent *)c
{
    return;
}

- (void)display:(int)depth
{
    return;
}

@end

(2)Leaf

@interface Leaf : ComComponent

- (Leaf *)initWithName:(NSString *)myName;

@end

@implementation Leaf

- (Leaf *)initWithName:(NSString *)myName
{
    if (self = [super initWithName:myName]) {

    }
    return self;
}

- (void)add:(ComComponent *)c
{
    NSLog(@"Can not add a leaf");
}

- (void)remove:(ComComponent *)c
{
    NSLog(@"Can not remove a leaf");
}

- (void)display:(int)depth
{
    NSLog(@"[%dLevel]%@", depth, name);
}

@end

(3)Composite

@interface Composite : ComComponent
{
    NSMutableArray *childrenArr;
}

- (Composite *)initWithName:(NSString *)myName;

@end

@implementation Composite

- (Composite *)initWithName:(NSString *)myName
{
    if (self = [super initWithName:myName]) {
        childrenArr = [NSMutableArray array];
    }
    return self;
}

- (void)add:(ComComponent *)c
{
    [childrenArr addObject:c];
}

- (void)remove:(ComComponent *)c
{
    [childrenArr removeObject:c];
}

- (void)display:(int)depth
{
    NSLog(@"[%dLevel]%@", depth, name);
    for (ComComponent *component in childrenArr) {
        [component display:depth+1];
    }
}

@end

(四)客户端调用

Composite *root = [[Composite alloc] initWithName:@"root"];
[root add:[[Leaf alloc] initWithName:@"Leaf A"]];
[root add:[[Leaf alloc] initWithName:@"Leaf B"]];

Composite *comp = [[Composite alloc] initWithName:@"Composite X"];
[comp add:[[Leaf alloc] initWithName:@"Leaf XA"]];
[comp add:[[Leaf alloc] initWithName:@"Leaf XB"]];
[root add:comp];

Composite *comp1 = [[Composite alloc] initWithName:@"Composite XY"];
[comp1 add:[[Leaf alloc] initWithName:@"Leaf XYA"]];
[comp1 add:[[Leaf alloc] initWithName:@"Leaf XYB"]];
[root add:comp1];

[root add:[[Leaf alloc] initWithName:@"Leaf C"]];
Leaf *leaf = [[Leaf alloc] initWithName:@"Leaf D"];
[root add:leaf];

[root remove:leaf];
[root display:1];

决定台出口结果:

2017-06-21 18:38:29.268670+0800 Composite[76962:2201266] [1Level]root 2017-06-21 18:38:29.269293+0800 Composite[76962:2201266] [2Level]Leaf A 2017-06-21 18:38:29.269322+0800 Composite[76962:2201266] [2Level]Leaf B 2017-06-21 18:38:29.269337+0800 Composite[76962:2201266] [2Level]Composite X 2017-06-21 18:38:29.269351+0800 Composite[76962:2201266] [3Level]Leaf XA 2017-06-21 18:38:29.269363+0800 Composite[76962:2201266] [3Level]Leaf XB 2017-06-21 18:38:29.269376+0800 Composite[76962:2201266] [2Level]Composite XY 2017-06-21 18:38:29.269387+0800 Composite[76962:2201266] [3Level]Leaf XYA 2017-06-21 18:38:29.269398+0800 Composite[76962:2201266] [3Level]Leaf XYB 2017-06-21 18:38:29.269408+0800 Composite[76962:2201266] [2Level]Leaf C

该例子总共有四个类包含叁个接口类ComComponents和四个接口类的子类,那样的话,我们得以平素在七个子类(Leaf和Composite)中去采取接口类中定义的办法,而且也能够重写方法。从而落成了咬合(Composite)和单个对象(Leaf)的1致性。

组合情势的显要意图是让树形结构中的各类节点有所同等的架空中接力口。那样任何结构能够用作三个合并的虚幻结构选拔,而不是暴光其里面表示。对各样结点的其他操作,能够经过磋商或抽象基类中定义的一模同样接口来拓展。

在Cocoa Touch
框架中,UIView被公司成多少个整合结构。每个UIView的实例能够包括UIView的其它实例,变成统1的树形结构。让客户端对单个UIView对象和UIView的3结合统一对待。

组成方式的裨益

  • 结合情势定义了包涵基本目的和构成对象的类等级次序结构。基本对象能够被组合成更复杂的三结合对象,而那几个组合对象又能够被重组,那样不断地递归下去,客户端代码中,任何用的的主干目的的地点都足以行使组合对象了。
  • 构成情势让客户可以同样地利用组合结商谈单个对象。

何时使用组合形式

  • 想博得对象抽象的树形表示(全体部分的档期的顺序结构)。
  • 想让客户端统一管理组合结构中的全部目标。

在Cocoa Touch框架中运用组合方式

在Cocoa Touch
框架中,UIView被协会成二个组成结构。各种UIView的实例能够分包UIView的其余实例,形成统一的树形结构。让客户端对单个UIView对象和UIView的整合统一对待。

例子

第1,大家先建叁个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)的1致性。

总结

整合格局的显要意图是让树形结构中的各类节点有所一样的空洞接口。那样全数结构能够作为1个联合的悬空结构选用,而不是暴光其中间表示。对每一个结点的其它操作,可以通过协商或抽象基类中定义的1致接口来进展

附:

相关文章