设计模式(四)----解释器模式、迭代器模式、命令模式、状态模式、备忘录模式、模板方法模式

解释器模式

       在我们给定一个语言,并定义它的语法和一个解释器,这个解释器用来标识语言中的句子,就是所谓的解释器模式。例如我们做一些字符串的替换,或者进行一些密文的解密,像特定的字符替换频率足够高的话,那么可以使用这种解释器模式来解决这种问题。

解释器模式类图.png

       图中我们定义了抽象解释器类Expression,声明一个抽象的解释操作。TerminalExpression是继承抽象表达式的终结表达式,例子中是最后将所有字符转换成小写字符并输出,定义的NoterminalExpression是将"*"的符号替换成"@"符号,也就可以理解为这个类是处理非终结符解释器。我们使用这种模式更多的是对场景的具体使用,如果要解释的内容很多的话,需要创建很多的非终结符解释器类,易引起类的膨胀,一些复杂的文法解释会比较难以维护。使用这种模式可以很好的进行解释扩展,只需新增解释器类,在一些简单的文法上比较容易实现。

       TerminalExpression的实现

- (NSString *)interpretStr:(NSString *)string
{
    return [string lowercaseString];
}

       NoterminalExpression的实现

- (NSString *)interpretStr:(NSString *)string
{
    return [string stringByReplacingOccurrencesOfString:@"*" withString:@"@"];
}

本节工程示例

迭代器模式

       迭代器模式主要用于顺序访问集合对象的元素,不需要知道集合对象中的底层表示。将数据存储和遍历的职责分离,增加新的迭代器和数据都很方便,无须修改原有代码,我们也可以自己定义数据的遍历方式。

迭代器模式类图.png

       图中我们定义了两个抽象类,迭代器抽象类Iterator定义了遍历的方式,容器抽象类Container定义了获取迭代器的接口,具体的实现由FruitsIterator类来完成。这个例子我们在外部给容器类进行的赋值,我们可以给定内部设置成集合类,这样就无须暴露它的内部表示,在迭代器类中我们可以添加方法来提供多种遍历方式。在使用迭代器模式的时候,我们需要增加新的迭代的话,不仅要增加聚合类,也要添加相应的迭代器类,这样会使类的个数成对的增加,一定程度上增加的系统的复杂性。

       FruitsIterator的实现

- (instancetype)initWithFruits:(NSArray *)fruits
{
    if (self = [super init]) {
        _fruits = fruits;
        _index = 0;
    }
    return self;
}

- (NSString *)first;
{
    return self.fruits.firstObject;
}

- (NSString *)next;
{
    if (self.index + 1 < self.fruits.count) {
        self.index ++;
        return self.fruits[self.index];
    }
    return nil;
}

- (NSString *)current;
{
    if (self.index < self.fruits.count) {
        return self.fruits[self.index];
    }
    return nil;
}

- (BOOL)hasNext;
{
    if (self.index + 1 < self.fruits.count) {
        return YES;
    }
    return NO;
}

- (BOOL)isFirst;
{
    if (self.index == 0) {
        return YES;
    }
    return NO;
}

- (BOOL)isLast;
{
    if (self.index == self.fruits.count - 1) {
        return YES;
    }
    return NO;
}

本节工程示例

命令模式

       命令模式的定义是将请求封装成一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

命令模式类图:

命令模式类图.png

如图定义了抽象的Receiver(接收者角色)和Command(命令角色),各自有自己的实际具体实现接收操作和命令操作,Invoker是命令的请求者,也是命令模式中的最重要角色,这个角色对各个命令进行控制。

Command1的实现

- (instancetype)initWithReceiver:(Receiver *)receiver
{
    if (self = [super init]) {
        _receiver = receiver;
    }
    return self;
}

- (void)execute
{
    [self.receiver doSomething];
}

本节工程示例

状态模式

状态模式是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。在一些情况下,一个对象的行为取决于其状态变化的属性,当这个对象和外部的事件产生互动时,它的内部状态会改变,同时使得系统的行为也发生变化。

状态模式类图:

状态模式类图.png

图中定义了抽象状态类State,拥有开始和停止状态,Context所持有的状态在两种状态的改变下,它会产生的行为变化。使用这种方式我们可以灵活的添加新的状态和行为,也可以让多个环境对象共享一个状态对象,从而减少系统中的个数,但使用状态模式容易增加系统类和对象的个数。

其中StartState的实现

- (void)doSomethingWithContext:(Context *)context;
{
    NSLog(@"运动状态");
    [context setState:self];
}

其中StopState的实现

- (void)doSomethingWithContext:(Context *)context;
{
    NSLog(@"停止状态");
    [context setState:self];
}

本节工程示例

备忘录模式

备忘录模式主要用来存储另外一个对象内部状态的快照对象。用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。

备忘录模式类图:

备忘录模式类图.png

备忘录模式中有三个角色,一个备忘录角色(Memento)它主要用来存储备忘发起者角色的内部状态,备忘发起角色(Originator)创建一个备忘录,用来记录此刻它的内部状态,在需要的时候使用备忘录恢复内部状态,还有个备忘录管理者角色(Caretaker),它负责保存好备忘录,它不能对备忘录的内容进行操作或者检查。使用这种模式给用户提供了一种可以恢复状态的机制,使用户能够比较方便地回到历史的状态,同时实现了信息额封装,用户不需要关心状态的保护细节。保存状态容易消耗资源,使类的成员变量过多。

其中Originator的实现

- (Memento *)saveStateToMemento
{
    return [[Memento alloc] initWithState:_state];
}

- (void)setState:(NSInteger)state
{
    _state = state;
}

- (NSInteger)getState
{
    return _state;
}

- (void)getStateFromMemento:(Memento *)memento
{
    _state = [memento getState];
}

本节工程示例

模板方法模式

模板模式是定义一个抽象类,它公开定义了执行它的方法的方式/模板,它的子类可以按需要重新写方法实现,但调用将以抽象类中的定义方式进行。

享元模式类图:

模板方法模式类图.png

如图定义了一个出去旅游类,定义了一些流程模板,打包、出游、游玩、返回这些旅游过程,其中我们使用了三套方案出行、汽车、飞机和火车,它们的交通方式都不一样,然后各自实现相应的步骤。

其中Travel的实现部分

- (void)package
{
    NSLog(@"打包");
}
- (void)goToPlace
{
    NSLog(@"出发");
}
- (void)play
{
    NSLog(@"游玩");
}
- (void)backHome
{
    NSLog(@"回家");
}

- (void)travel
{
    [self package];
    [self goToPlace];
    [self play];
    [self backHome];
}

本节工程示例

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,940评论 1 15
  • 1 场景问题# 1.1 开发仿真系统## 考虑这样一个仿真应用,功能是:模拟运行针对某个具体问题的多个解决方案,记...
    七寸知架构阅读 2,143评论 1 50
  • 当你踏上南方的土地 在异乡的街头沐浴着春风 你说你常常想起小时候 熟悉的故园里 柳绿花红 我依旧坚守在北方的旷野 ...
    兔子的菜园阅读 408评论 7 17
  • 文/兰舟酱 蛤蟆是一种奇妙的动物。蛤蟆的口腔中没有锐利的牙齿,他不咬人,仅于无声时,冷不丁的,黏嗒嗒的,带着...
    兰舟酱阅读 681评论 0 2
  • 你已经是大人了 你没有能力讨好 你已经没有灵魂了 在乎那些有用吗 连生命都没什么用了 但是你身上还有重担 所以,你才活着
    心不尘封阅读 150评论 0 0