IOS设计架构模式:迭代器模式和组合模式

一、迭代器模式

1、什么是迭代器模式?

     提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。迭代器是 iOS 中运用的最多的模式之一,你用到的NSArray``NSDictionary``NSSet等都是迭代器模式的实现,是 iOS 已经完整实现了的。如果你有详细的翻一下它们存在的属性的话,应该会注意到有一个属性叫objectEnumeratorreverseObjectEnumerator它们就是具体的迭代器,通过next顺序访问。举个例子:

// 1. 数组集合
    NSArray *data = @[@"1",@"2",@"3",@"4"];
    
    // 2.创建迭代器
    NSEnumerator *enumerator = [data objectEnumerator];
    
    // 3.访问每一个元素
    id obj = nil;
    while (obj = [enumerator nextObject]) {
        NSLog(@"---%@",obj);
    }

2、迭代器的设计

       迭代器就好比是遥控器选台。电视的所有台就是个集合类,而遥控器就是迭代器。

要写迭代器,首先要有一个集合类(线性表),创建集合类LinkedList(线性链表)需要先创建节点Node,最后才能创建迭代器LinkedIterator,下图是线性表:

节点类

Node.h

#import <Foundation/Foundation.h>

@interface Node : NSObject

// 指向下一个节点(链表中的指针)
@property (nonatomic, strong) Node *nextNode;

// 节点里面的data
@property (nonatomic, strong) id data;

// 节点数据
+ (instancetype)nodeData:(id)data;

@end

Node.m

#import "Node.h"

@implementation Node

+ (instancetype)nodeData:(id)data {
    Node *node = [[self alloc] init];
    node.data = data;
    
    return node;
}
@end

线性链表类

LinkedList.h

#import <Foundation/Foundation.h>
#import "Node.h"

@interface LinkedList : NSObject

@property (nonatomic, strong) Node *headNode; /**< 头结点 */

/**
 链表中的节点数
 */
@property (nonatomic, assign) NSInteger numberOfNode;

- (void)addData:(id)data; /**< 节点上的数据 */

@end

LinkedList.m

#import "LinkedList.h"

@implementation LinkedList

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.headNode = [Node new];
    }
    return self;
}

- (void)addData:(id)data {
    // 1. 头节点为空,就添加
    if (self.headNode == nil) {
        
        self.headNode = [Node nodeData:data];
        
    } else {
        [self addData:data node:self.headNode];
    }
    
    // 数量的增加
    self.numberOfNode++;
}

// 2. 有头结点了,就插入到下一个节点
- (void)addData:(id)data node:(Node *)node {
    
    if (node.nextNode == nil) {
        node.nextNode = [Node nodeData:data];
    } else {
        // 当下一个节点也有值了,进行递归调用
        [self addData:data node:node.nextNode];
    }
}


@end

迭代器类

IteratorProtocol.h

#import <Foundation/Foundation.h>

@protocol IteratorProtocol <NSObject>

// 下一个对象
- (id)nextObject;
@end

LinkedIterator.h

#import <Foundation/Foundation.h>
#import "LinkedList.h"
#import "IteratorProtocol.h"

@interface LinkedIterator : NSObject <IteratorProtocol>

// 迭代器的实现方法
+ (instancetype)linkedObjectIterator:(LinkedList *)linkedList;
@end

LinkedIterator.m

#import "LinkedIterator.h"

@interface LinkedIterator ()

@property (nonatomic, strong) LinkedList *linkedList;

@property (nonatomic, strong) Node *currentNode;

@end

@implementation LinkedIterator

+ (instancetype)linkedObjectIterator:(LinkedList *)linkedList {
    // 1.初始化迭代器
    LinkedIterator *linkedIterator = [[LinkedIterator alloc] init];
    
    // 2. 保存链表数据
    linkedIterator.linkedList = linkedList;
    linkedIterator.currentNode = linkedList.headNode;
    
    return linkedIterator;
}

- (id)nextObject {
    self.currentNode = self.currentNode.nextNode;
    
    return self.currentNode;
}

@end

对迭代器进行应用

ViewController.m

// 1.创建集合类
    self.list = [[LinkedList alloc] init];
    [self.list addData:@"A"];
    [self.list addData:@"B"];
    [self.list addData:@"C"];

    // 2.迭代器的创建
    LinkedIterator *linkedIterator = [LinkedIterator linkedObjectIterator:self.list];

    // 3.访问每一个元素
    Node *node = nil;
    while (node = [linkedIterator nextObject]) {
        NSLog(@"---%@",node.data);
    }

3、深层处应用

       能够遍历类的私有属性。demo如下:

IteratorProtocol.h

#import <Foundation/Foundation.h>

@protocol IteratorProtocol <NSObject>

// 下一个对象
- (id)nextObject;

// 重置迭代器指针
- (void)resetIterator;

@end

TZView.h

#import <UIKit/UIKit.h>
#import "IteratorProtocol.h"

@interface TZView : UIView <IteratorProtocol>

@end

TZView.m

#import "TZView.h"
#import "LinkedList.h"

@interface TZView ()

@property (nonatomic, strong) UIButton *tzBtn;
@property (nonatomic, strong) UILabel *tzLabel;
@property (nonatomic, strong) UITextField *tzTextField;

@property (nonatomic, strong) LinkedList *linkedList;
@property (nonatomic, strong) Node *currentNode;

@end

@implementation TZView

- (instancetype)initWithFrame:(CGRect)frame{
    
    self = [super initWithFrame:frame];
    if (self) {
        
        self.tzBtn = [[UIButton alloc] initWithFrame:self.bounds];
        self.tzLabel  = [[UILabel alloc] initWithFrame:self.bounds];
        self.tzTextField  = [[UITextField alloc] initWithFrame:self.bounds];
        
        [self addSubview:self.tzBtn];
        [self addSubview:self.tzLabel];
        [self addSubview:self.tzTextField];
        
        // 初始化
        self.linkedList = [[LinkedList alloc] init];
        [self.linkedList addData:self.tzBtn];
        [self.linkedList addData:self.tzLabel];
        [self.linkedList addData:self.tzTextField];
        
        self.currentNode = self.linkedList.headNode;
    }
    return self;
}


#pragma mark - IteratorProtocol
- (id)nextObject {
    self.currentNode = self.currentNode.nextNode;
    return self.currentNode;
}

- (void)resetIterator {
    self.currentNode = self.linkedList.headNode;
}

@end

ViewController.m

#import "ViewController.h"
#import "TZView.h"
#import "Node.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    TZView *view = [[TZView alloc] initWithFrame:self.view.bounds];
    Node *node = nil;
    
    [view resetIterator];
    while (node = [view nextObject]) {
        NSLog(@"%@", node.data);
    }
    [view resetIterator];
    while (node = [view nextObject]) {
        NSLog(@"%@", node.data);
    }
}


@end

二、组合模式

1、什么是组合模式

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

2、组合模式用在什么地方

  • 在程序中有树形结构的时候使用
  • 忽略组合对象与单个对象的不同,进行统一处理的时候。

UIView 对于两者都符合,结构上属于树形结构,不管是 view 还是他的 subView 都可以进行默认的处理。

3、组合模式的使用

  1. 创建类,定义添加、移除和检索所有节点的方法
  2. 创建数组,实现添加等方法。

在这里,我暂时把枝节点和叶结点的实现合为一体,在数组个数中做判断,个数为 0 的即位叶结点。

4、demo

创建节点类Node,定义添加、移除和检索所有节点的方法

Node.h

#import <Foundation/Foundation.h>

@interface Node : NSObject
// 节点名字
@property (nonatomic, copy) NSString *nodeName;

// 子节点集合
@property (nonatomic, strong) NSMutableArray<Node *> *childNode;

// 初始化
+ (instancetype)nodeWithNodeName:(NSString *)nodeName;

// 添加子节点
- (void)addNode:(Node *)node;

// 删除子节点
- (void)removeNode:(Node *)node;

// 获取子节点
- (Node *)nodeAtIndex:(NSInteger)index;


// 打印Node
- (void)operation;


@end

Node.m

#import "Node.h"

@implementation Node

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.childNode = [NSMutableArray array];
    }
    return self;
}

// 初始化
+ (instancetype)nodeWithNodeName:(NSString *)nodeName {
    Node *node = [[[self class] alloc] init];
    node.nodeName = nodeName;
    
    return node;
}

// 添加子节点
- (void)addNode:(Node *)node {
    [self.childNode addObject:node];
}

// 删除子节点
- (void)removeNode:(Node *)node {
    [self.childNode removeObject:node];
}

// 获取子节点
- (Node *)nodeAtIndex:(NSInteger)index {
    if (index >= self.childNode.count) {
        return nil;
    
    } else {
        return self.childNode[index];
    }
}

// 打印Node
- (void)operation {
    NSLog(@"nodeName =  %@", self.nodeName);
}

- (NSString *)description {
    return [NSString stringWithFormat:@"node - %@",self.nodeName];
}

@end

ViewController.m

#import "ViewController.h"
#import "Node.h"

@interface ViewController ()
// 根节点
@property (nonatomic, strong) Node *rootNode;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 创建根节点
    self.rootNode = [Node nodeWithNodeName:@"A"];
    
    // 创建第一级字节点
    Node *b = [Node nodeWithNodeName:@"B"];
    [self.rootNode addNode:b];
    Node *c = [Node nodeWithNodeName:@"C"];
    [self.rootNode addNode:c];
    Node *d = [Node nodeWithNodeName:@"D"];
    [self.rootNode addNode:d];
    
    // 创建第二级子节点
    [c addNode:[Node nodeWithNodeName:@"E"]];
    [c addNode:[Node nodeWithNodeName:@"F"]];
    
    [self.rootNode removeNode:b];
    
    NSLog(@"%@", c.childNode);
    NSLog(@"---%@", self.rootNode.childNode);
}

@end

打印结果:

2019-02-07 12:48:04.641707+0800 TreeDemo2[3428:358320] (

    "node - E",

    "node - F"

)

2019-02-07 12:48:04.641888+0800 TreeDemo2[3428:358320] ---(

    "node - C",

    "node - D"

)

5、优缺点

优点: 
1、组合模式解耦了程序和各元素内部结构,可以把复杂的程序像单个接口一样处理该程序 
2、高层模块调用简单 
3、节点自由增加 
缺点: 
1、违反了依赖倒置原则,而接口不应该依赖于具体的实现类。比如树形的结构的时候,其叶子和树叶的声明都是实现类。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值