• 设计模式应用场景之Model设计中可以用到的设计模式


    在开发中,不同的场景适用不同的设计模式。对于开发建模方面,可以根据模型的抽象类型设计成简单属性模式和复杂组合模式。
    因为组合模式中的属性为多种类型对象,可操作性也比较灵活。
    而针对这种复杂数据结构,有两种设计模式可以使用:
    1.组合模式
    2.迭代器模式
     
    组合模式篇
    组合模式简介:
    1.组合模式就是一个树形数据结构
    2.对组合对象的查询,访问都是递归操作。
    3.所有的节点都会实现同一套接口或者继承自 同一个抽象父类。
    4.每个对象都是其中的一个节点,无论叶子节点和组件节点都有相同的接口。只是叶子节点的接口返回为空,组件节点的接口实现接口。
    5.组合模式让我们把相同基类型的对象组合到树状结构中,其中父节点包含同类型的子节点
     
    组合模式的对象图如下:
    aComposite:组件节点,下面包含子节点
    aLeaf:叶子节点,下面没有子节点。
     
    组合模式的类图如下:
    aComposite:组件节点中包含的动作如下:
    1.基本操作
    2.对子节点的各种操作(增,删,查)
     
    aLeaf:叶子节点总包含的动作如下:
    1.基本操作
    因为叶子节点是最底层,最简单的节点,所以它所包含的动作也是最简单的,只有作用节点最基本的operation功能。
     
    组合模式的作用:
    1.将对象组合成树形结构,以表示“整体-部分”的层次结构
    2.组合模式使得客户端对单个对象和组合对象的操作具有一致性。使客户端对组件节点和叶子节点进行处理时,能够对它们的区别无感知,好像它们都是同样的简单对象。
     
    组合模式的实际使用例子:
    线段轨迹这个抽象事物为例子,这个抽象例子中包含三种模型:
    1.线段,它是一个组合模式模型,里面可以包含子线段,连接点,点。
    2.连接点,它是线段(或子线段)中的内容连接部分。
    3.点,只有一个点的线段或者长度为0的线段。
     
    这三种抽象事物的类UML图如下:
     
    这三种抽象事物的对象UML图如下:
     

    代码实现如下:

     1.先定义这三个类所共同遵守的协议:Mark协议
    @protocol Mark <NSObject,NSCopying>
    @property (nonatomic, strong) UIColor *color;
    @property (nonatomic, assign) CGSize size;
    @property (nonatomic, assign) CGPoint location;
    - (void)addMark:(id<Mark>)mark;
    - (void)removeMark:(id<Mark>)mark;
    - (void)removeAllMarks;
    - (id<Mark>)childAtIndex:(int)index;
    - (id<Mark>)lastChild;
    - (NSUInteger)count;
    @end
    

    2.Stroke类实现Mark协议如下:

    @interface Stroke()
    @property (nonatomic, strong) NSMutableArray<id<Mark>> *markArray;
    @end
    
    @implementation Stroke
    @synthesize color,location,size;
    #pragma mark - 属性操作
    - (void)setLocation:(CGPoint)location {}
    - (CGPoint)location {
        if (_markArray.count) {
            return [[_markArray firstObject] location];
        } else {
            return CGPointZero;
        }
    }
    #pragma mark - Mark操作
    - (NSMutableArray<id<Mark>> *)markArray {
        if (!_markArray) {
            _markArray = @[].mutableCopy;
        }
        return _markArray;
    }
    
    - (void)addMark:(id<Mark>)mark {
        [self.markArray addObject:mark];
    }
    
    - (void)removeMark:(id<Mark>)mark {
        //在当前节点中,就从当前节点删除,不在当前节点,就深度查找子节点
        if ([_markArray containsObject:mark]) {
            [self.markArray removeObject:mark];
        } else {
            [_markArray makeObjectsPerformSelector:@selector(removeMark:) withObject:mark];
        }
    }
    
    - (void)removeAllMarks {
        [self.markArray removeAllObjects];
    }
    
    - (id<Mark>)childAtIndex:(int)index {
        if (self.markArray.count == 0) {
            return nil;
        } else {
            return self.markArray[index];
        }
    }
    
    - (id<Mark>)lastChild {
        return self.markArray.lastObject;
    }
    
    - (NSUInteger)count {
        return self.markArray.count;
    }
    3.Vertex实现Mark协议如下:
     
    @implementation Vertex
    @synthesize location;
    @dynamic color,size;
    
    - (instancetype)initWithLocation:(CGPoint)location {
        self = [super init];
        if (self) {
            self.location = location;
        }
        return self;
    }
    
    #pragma mark - 属性操作
    - (UIColor *)color{return nil;}
    - (void)setColor:(UIColor *)color{}
    - (CGSize)size{return CGSizeZero;}
    - (void)setSize:(CGSize)size{}
    
    #pragma mark - Mark操作
    - (void)addMark:(id<Mark>)mark {}
    - (void)removeMark:(id<Mark>)mark {}
    - (void)removeAllMarks {}
    - (id<Mark>)childAtIndex:(int)index {return nil;}
    - (id<Mark>)lastChild {return nil;}
    - (NSUInteger)count {return 0;}

    4.Dot类实现Mark协议如下:

    @interface Dot : Vertex
    @end
    
    @implementation Dot
    @synthesize color,size;

    因为Dot类基础自Vertex,所以对象Mark对象的操作使用父类的就好了

    迭代器模式篇

    迭代器模式简介:

    1.迭代器提供了一种 顺序访问聚合对象(集合)中元素的方法,而无需暴露聚合对象(集合)的底层表示和结构细节。
    2. 为聚合对象(集合)配置迭代器后,遍历集合元素的任务从集合 转移给了迭代器对象。
    3.请问啥叫迭代器模式?
    答:针对抽象集合的迭代行为 而采用的设计模式,叫做迭代器模式
     
    迭代器模式的对象图如下:
     

    简单表示,迭代器持有着聚合对象

     
    标准表示:
    1.抽象聚合体Aggregate中定义了创建迭代器的接口,实例聚合类ConcreteAggregate实现创建迭代器的接口,返回自己类型的迭代器。
    2.抽象迭代器Iterator定义了通用迭代方法,实例迭代器ConcreteIterator实现迭代方法接口。
     
    迭代器模式的种类:
    1.外部迭代器
    由聚合对象直接将自己的迭代器返回给调用者,调用者进行灵活使用,举例如下:
    NSEnumerator *enumerator = [self enumerator];
        id <Mark> mark;
        while (mark = [enumerator nextObject]) {
            [mark lastChild]
        }
    2.内部迭代器
    由聚合体提供一个迭代接口,这个迭代接口中有一个参数,该参数需要传递一个供聚合体内部在遍历时调用的“代码块”。这样在
    聚合体内部遍历时,就将每个对象执行传递过来的预先定义好的函数。
    举例如下:
     
        self.stroke = [Stroke new];
        [self.stroke enumerateMarksUsingBlock:^(id<Mark> mark, BOOL *stop) {
            
        }]

    迭代器模式的实际使用例子:

    现在继续使用刚才使用举的抽象事物“线段轨迹”
    这个抽象例子中包含三种模型:线段,连接点,点。
     
     在Mark协议中定义迭代器接口,返回外部迭代器
     

    代码实现如下:

    Mark协议接口定义

    @protocol Mark <NSObject,NSCopying>
    @property (nonatomic, strong) UIColor *color;
    @property (nonatomic, assign) CGSize size;
    @property (nonatomic, assign) CGPoint location;
    - (void)addMark:(id<Mark>)mark;
    - (void)removeMark:(id<Mark>)mark;
    - (void)removeAllMarks;
    - (id<Mark>)childAtIndex:(int)index;
    - (id<Mark>)lastChild;
    - (NSUInteger)count;
    - (instancetype)copy;
    //迭代器
    - (NSEnumerator *)enumerator;
    @end;

    Stroke类接口实现

    @interface Stroke()
    @property (nonatomic, strong) NSMutableArray<id<Mark>> *markArray;
    @end
    
    @implementation Stroke
    @synthesize color,location,size;
    #pragma mark - 属性操作
    - (void)setLocation:(CGPoint)location {}
    - (CGPoint)location {
        if (_markArray.count) {
            return [[_markArray firstObject] location];
        } else {
            return CGPointZero;
        }
    }
    #pragma mark - Mark操作
    - (NSMutableArray<id<Mark>> *)markArray {
        if (!_markArray) {
            _markArray = @[].mutableCopy;
        }
        return _markArray;
    }
    
    - (void)addMark:(id<Mark>)mark {
        [self.markArray addObject:mark];
    }
    
    - (void)removeMark:(id<Mark>)mark {
        //在当前节点中,就从当前节点删除,不在当前节点,就深度查找子节点
        if ([_markArray containsObject:mark]) {
            [self.markArray removeObject:mark];
        } else {
            [_markArray makeObjectsPerformSelector:@selector(removeMark:) withObject:mark];
        }
    }
    
    - (void)removeAllMarks {
        [self.markArray removeAllObjects];
    }
    
    - (id<Mark>)childAtIndex:(int)index {
        if (self.markArray.count == 0) {
            return nil;
        } else {
            return self.markArray[index];
        }
    }
    
    - (id<Mark>)lastChild {
        return self.markArray.lastObject;
    }
    
    - (NSUInteger)count {
        return self.markArray.count;
    }
    
    #pragma mark - 迭代器
    - (NSEnumerator *)enumerator {
        return [[ZHFMarkEnumerator alloc] initWithMark:self];
    }
     在Mark协议中定义内部迭代器接口:
     
     

    代码实现如下:

    Mark协议接口定义
    @protocol Mark <NSObject,NSCopying>
    @property (nonatomic, strong) UIColor *color;
    @property (nonatomic, assign) CGSize size;
    @property (nonatomic, assign) CGPoint location;
    - (void)addMark:(id<Mark>)mark;
    - (void)removeMark:(id<Mark>)mark;
    - (void)removeAllMarks;
    - (id<Mark>)childAtIndex:(int)index;
    - (id<Mark>)lastChild;
    - (NSUInteger)count;
    - (instancetype)copy;
    //迭代器
    - (NSEnumerator *)enumerator;
    //内部迭代器
    - (void)enumerateMarksUsingBlock:(void (^) (id <Mark> mark, BOOL *stop))block;
    @end;
    Stroke类接口实现
     
    @interface Stroke()
    @property (nonatomic, strong) NSMutableArray<id<Mark>> *markArray;
    @end
    
    @implementation Stroke
    @synthesize color,location,size;
    #pragma mark - 属性操作
    - (void)setLocation:(CGPoint)location {}
    - (CGPoint)location {
        if (_markArray.count) {
            return [[_markArray firstObject] location];
        } else {
            return CGPointZero;
        }
    }
    #pragma mark - Mark操作
    - (NSMutableArray<id<Mark>> *)markArray {
        if (!_markArray) {
            _markArray = @[].mutableCopy;
        }
        return _markArray;
    }
    
    - (void)addMark:(id<Mark>)mark {
        [self.markArray addObject:mark];
    }
    
    - (void)removeMark:(id<Mark>)mark {
        //在当前节点中,就从当前节点删除,不在当前节点,就深度查找子节点
        if ([_markArray containsObject:mark]) {
            [self.markArray removeObject:mark];
        } else {
            [_markArray makeObjectsPerformSelector:@selector(removeMark:) withObject:mark];
        }
    }
    
    - (void)removeAllMarks {
        [self.markArray removeAllObjects];
    }
    
    - (id<Mark>)childAtIndex:(int)index {
        if (self.markArray.count == 0) {
            return nil;
        } else {
            return self.markArray[index];
        }
    }
    
    - (id<Mark>)lastChild {
        return self.markArray.lastObject;
    }
    
    - (NSUInteger)count {
        return self.markArray.count;
    }
    
    #pragma mark - 迭代器
    - (NSEnumerator *)enumerator {
        return [[ZHFMarkEnumerator alloc] initWithMark:self];
    }
    
    - (void)enumerateMarksUsingBlock:(void (^)(id<Mark>, BOOL *stop))block {
        NSEnumerator *enumerator = [self enumerator];
        id <Mark> mark;
        BOOL *stop = NO;
        for (id <Mark> mark in enumerator) {
            block(mark, &stop);
            if (stop) {
                break;
            }
        }
    }
    熟练使用设计模式是编写高扩展,高稳定,高复用,三高代码很重要的一项技能。愿你我一同砥砺前行。
    完整的项目代码地址如下:
    目前项目还没有完全结束,处于持续完善中...
     
  • 相关阅读:
    查看SQL Server版本号(2005 & 2008)
    Installing an App for Testing
    Viewstate 的用法
    How to Open the Pdf file?
    工具类:Log
    SPSiteDataQuery and SPQuery
    SPSite, SPWeb Dispose and Class Design Partter
    Add Properties or Delete List Folder Content Type
    SharePoint UserControl
    Click Once 布署
  • 原文地址:https://www.cnblogs.com/zhou--fei/p/10161559.html
Copyright © 2020-2023  润新知