object-c 策略模式

来源:互联网 发布:java编程是不是简单点 编辑:程序博客网 时间:2024/05/16 05:34


策略模式的定义,《HeadFirst》这本书,定的比较详细,此文不作过多描述。

对于策略模式,将从下面几个方面进行分析:

方面一:策略模式和适用的场景。

1.类中定义了很多条件判断语句来进行不同的选择。

2.不想把类中的具体细节,数据结构暴露给调用者。

这种说法好似放之四海而皆准,太过朦胧,有点雾里看花。下面使用一个常见的例子来说明。


以生活中面试为例:一个公司有不同的岗位(Cocos2d手游、Python 、ai工程师、设计),有A,B ,C,D

等应聘者前来面试不同的工作岗位。这个公司有个规定,需要应聘者做相应的笔试题目。

如果不用策略模式实现的话可能会写成这样:


  if  "Cocos2d手游":

       做 Cocos2d手游 题目

  else if "Python":

     做 python 题目:


这种情况 如果条件语句比较少的话,没什么问题 ,但是在更新的时候可能就比较烦了,需要扩展这个条件判断语句

即把自己的条件语句加到上面这段代码中。这对于代码设计而言对于结构不太友好,且对于过多的条件语句,难以维护。而策略模式,生就是为了解决这种问题的。


方面二:策略模式类的角色分析。

     角色一:抽象策略基类,这个类是用来封装规范接口的,对于策略执行者而言它是不知道具体的策略内容的。

     在整个模式中,担任2个角色:保持具体策略的引用,规范接口。

    

   角色二:具体的策略类,这个类需要扩展抽象策略基类,统一规范接口。方便使用基类引用时进行调用。

在上面的例子中可理解为:不同的岗位(Cocos2d手游、Python 、ai工程师、设计)对应的笔试题目。


   角色三:策略选择器,由谁来分发策略。上面的例子中,这个角色一般由HR来担任。很明显,HR需要知道策略(具体的策略内容可以不知道),然后根据不同的应聘者选择不同的笔试题目。



下面根据这三个角色来进行笔试题目分发:

 抽象基类:


#import <Foundation/Foundation.h>/** 策略基类,规范策略执行的接口,具体的策略由各自的策略对象去执行 */@interface StrategyBase : NSObject/** 执行策略 */-(void) executeStrategy;@end

。m文件:

#import "StrategyBase.h"@implementation StrategyBase-(void) executeStrategy{        NSLog(@"如果不定义具体的策略,我就执行默认的策略");}@end


具体的策略类:这里只用Cocos2d 与python为例:

Cocos2dStrategy.h:

#import <Foundation/Foundation.h>#import "StrategyBase.h"@interface Cocos2dStrategy : StrategyBase//重载基类的 执行策略接口,可以不必在头文件中进行声明,这样写只是为了规范-(void) executeStrategy;@end

.m文件:

#import "Cocos2dStrategy.h"@implementation Cocos2dStrategy-(void) executeStrategy{    NSLog(@"cocos2d 岗位需要,选择这里的策略");}@end


同理python。h文件为:

#import <Foundation/Foundation.h>#import "StrategyBase.h"@interface PythonStrategy : StrategyBase-(void)executeStrategy;@end



.m文件:

#import "PythonStrategy.h"@implementation PythonStrategy-(void) executeStrategy{        NSLog(@"Python 岗位,选择这这里的策略");}@end


策略选择器,也即为HR扮演的角色:

#import <Foundation/Foundation.h>#import "StrategyBase.h"/** 策略选择器,负责选择具体的策略 因为具体的策略,在客户端选择之前是未定的,所以需要用策略基类来保持具体的策略的引用 */@interface StrategySelecter : NSObject/** 策略引用保持者 */@property(nonatomic,retain) StrategyBase* strategy;+(instancetype) getInstance;/** 选择策略 @param strategy 具体的策略对象 */-(void) selectStrategy:(StrategyBase*) strategy;/** 执行策略  这个方法其实可以省略,为了方便阅读,与解偶合执行的动作放在这里 */-(void) executeStrategy;@end


.m文件:



////  StrategySelecter.m//  DesignPattern////  Created by 刘小兵 on 2017/7/21.//  Copyright © 2017年 刘小兵. All rights reserved.//#import "StrategySelecter.h"static StrategySelecter* strategyInstance = nil;@implementation StrategySelecter+(instancetype) getInstance{    @synchronized (self) {        if(strategyInstance == nil){                    strategyInstance = [[StrategySelecter alloc] init];        }    }    return strategyInstance;}-(void) selectStrategy:(StrategyBase*) strategy{    self.strategy = strategy;        //高手一般都能看出来,策略选择器中的那个基类策略引用保持者,只 是为了代码的扩展性,如果没有那个引用    // [strategy executeStrategy ];}-(void) executeStrategy{        if(self.strategy){            [self.strategy executeStrategy];    }}@end


测试方式:

StrategySelecter* selector = [StrategySelecter getInstance];        Cocos2dStrategy* cocos2d = [[Cocos2dStrategy alloc] init];            [selector selectStrategy:cocos2d];            [selector selectStrategy:[[PythonStrategy alloc] init]];


测试结果:




原创粉丝点击