英雄联盟中的设计模式-模版方法模式

在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

在英雄联盟中备受关注的人物莫过于盲僧了。作为一个刺客,有着飘逸的技能,今儿,就在这里讨论一下盲僧开团的连招。


英雄联盟中的设计模式-模版方法模式_第1张图片

盲僧开团的连招可以用多种方式来完成,但归根结底就是要将对手踢回到友军身边。要达到这个目的,首先需要接近目标,然后要移动到目标的身后方,最后使用R技能神龙摆尾使目标发生位移。既然基本的流程已经定了下来,那最好使用模版方法模式来完成设计,毕竟我们不想定下来的流程有任何改变。

首先来看一下类图:


英雄联盟中的设计模式-模版方法模式_第2张图片

我们使用抽象类将整个连招的流程梳理出来,虽然流程已经定了下来,但是某些步骤的细节却各不相同,因此我们将nearTargettoBackside方法定义成抽象方法,子类可以在里面实现自己的细节。

部分实现代码:

@implementation BlindMonkContinueSkill
// 对外公开的连招方法,这里定义了连招的流程
- (void)continueSkill {
    [self nearTarget];
    [self toBackside];
    [self kickback];
}
- (void)kickback {
    NSLog(@"使用神龙摆尾将目标踢回来");
}
- (void)nearTarget { NSAssert(YES, @"抽象方法"); }
- (void)toBackside { NSAssert(YES, @"抽象方法"); }
@end

简单的说,模版方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
现在子类可以去实现“靠近目标”与“到目标背后”这些细节方法了:

// 第一个盲僧的连招细节
@implementation BlindMonk_1
- (void)nearTarget {
    NSLog(@"%@使用回音击接近目标", NSStringFromClass(self.class));
}
- (void)toBackside {
    NSLog(@"使用金钟罩到目标背后");
}
@end

// 第二个盲僧的连招细节
@implementation BlindMonk_2
- (void)nearTarget {
    NSLog(@"%@使用金钟罩接近目标", NSStringFromClass(self.class));
}
- (void)toBackside {
    NSLog(@"使用闪现到目标背后");
}
@end

最后我们调用continueSkill方法进行连招:

BlindMonk_1 *blindMonk1 = [[BlindMonk_1 alloc] init];
[blindMonk1 continueSkill];
NSLog(@"------------分割线--------------");
BlindMonk_2 *blindMonk2 = [[BlindMonk_2 alloc] init];
[blindMonk2 continueSkill];

使用模版方法带来的好处大致如下:

  1. 避免了重复的代码实现,比如kickback方法
  2. 有效的保护了整个连招流程
  3. 整个连招流程只在一个地方出现,所以更容易维护
  4. 提供了一个框架,使得各种各样的盲僧可以容易的接进来,他们只需要实现自己的细节方法便可

细心的观众可能发现了在抽象类中有一个leaveBattlefield方法,这就是传说中的钩子,钩子是被声明在抽象类中的方法,可以让子类有能力对整个连招流程的不同点进行挂钩。下面介绍钩子的一种用法:

/* 抽象类BlindMonkContinueSkill */
- (void)continueSkill {
    [self nearTarget];
    [self toBackside];
    [self kickback];
    // 进行挂钩处理
    if ([self leaveBattlefield]) {
        [self leave];
    }
}
// 钩子,子类可以选择性的覆盖此方法
// 默认返回YES,表示离开战场
- (BOOL)leaveBattlefield {
    return YES;
}

/* 在类BlindMonk_2中返回NO,表示不离开战场 */
-(BOOL)leaveBattlefield {
    return NO;
}

这样,子类就可以控制在整个连招中是否执行某些步骤。测试结果如下:

英雄联盟中的设计模式-模版方法模式_第3张图片

点击这里获取完成代码

并不是所有的盲僧都瞎,你瞧BlindMonk_1,一顿飘逸操作后,还能潇洒离开战场。


最后,你可能觉着模版方法模式与策略模式有些相似,其实他们还是有区别的:前者使用继承,后者使用组合。还有,之前提到的工厂方法,其实就是模版方法的特殊版本。

倾情告白:模版方法模式由超类主控一切,当有需要的时候,自然会去调用子类。另外,钩子可以让子类实现流程中可选的部分,或者在钩子对于子类的实现并不重要的时候,子类可以忽略钩子。钩子的另一个用法是让子类有机会对模版方法中某些即将发生的(或刚刚发生的)步骤作出反应。例如viewWillAppear:等一系列方法。

关注微信公众号CodingArtist,可以第一时间得到文章更新通知! _

你可能感兴趣的:(英雄联盟中的设计模式-模版方法模式)