定义:
工厂模式的思想主要为:多个类似的子类继承同一个父类,对其父类中的变量进行操作;工厂类负责判断、控制哪个子类被执行,而工厂类调用子类完成后,返回的结果是该子类的父类,该父类中的变量已经被操作过了,访问该父类,得到我们想要的结果
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
1. 相似:
在模式结构上,两者很相似;
2.差别:
用途不一样
工厂是创建型模式,它的作用就是创建对象;
策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;
关注点不一样
一个关注对象创建
一个关注行为的封装
解决不同的问题
工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。
策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
工厂相当于黑盒子,策略相当于白盒子;
策略模式例子
例1、
(1)策略模式的核心就是对算法变化的封装。
定义一个通用算法协议,让每个算法遵守其规则。
@protocol LHPlayerProtocol <NSObject> /** * Player开启视频 * * @return 描述(只为举例需要) */ - (NSString *)lh_play; /** * Player暂停视频 * * @return 描述(只为举例需要) */ - (NSString *)lh_pause; /** * Player停止播放 * * @return 描述(只为举例需要) */ - (NSString *)lh_stop;
AVPlayer的算法封装
#import <Foundation/Foundation.h> #import "LHPlayerProtocol.h" @interface LHAVPlayer : NSObject<LHPlayerProtocol> @end #import "LHAVPlayer.h" #import "AVPlayer.h" @interface LHAVPlayer () { id<AVPlayerProtocol> player;// AVPlayer播放器自身的协议 } @end @implementation LHAVPlayer - (instancetype)init { self = [super init]; if (self) { player = [[AVPlayer alloc] init];// 初始化AVPlayer播放器对象 } return self; } // 播放 - (NSString *)lh_play{ return [player a_play]; } // 暂停 - (NSString *)lh_pause{ return [player a_pause]; } // 停止 - (NSString *)lh_stop{ return [player a_stop]; } - (void)dealloc { player = nil; } @end
IJKPlayer的算法封装
#import <Foundation/Foundation.h> #import "LHPlayerProtocol.h" @interface LHIJKPlayer : NSObject<LHPlayerProtocol> @end #import "LHIJKPlayer.h" #import "Ijkplayer.h" @interface LHIJKPlayer () { id<IjkplayerProtocol> player;// IJKPlayer播放器自身的协议 } @end @implementation LHIJKPlayer - (instancetype)init { self = [super init]; if (self) { player = [[Ijkplayer alloc] init];// 初始化IJKPlayer播放器对象 } return self; } // 播放 - (NSString *)lh_play{ return [player i_play]; } // 暂停 - (NSString *)lh_pause{ return [player i_pause]; } // 停止 - (NSString *)lh_stop{ return [player i_stop]; } - (void)dealloc { player = nil; } @end
(2)策略模式中另一个核心类Context的定义
通用播放器类LHPlayer的定义。根据不同的策略选择不同的算法。
#import <Foundation/Foundation.h> #import "LHPlayerProtocol.h" // 播放器的类型 typedef enum : NSUInteger { EPlayerType_AVPlayer, EPlayerType_IJKPlayer } EPlayerType; @interface LHPlayer : NSObject - (instancetype)initWithType:(EPlayerType)type; /** * 开启视频 * * @return 描述(只为举例需要) */ - (NSString *)play; /** * 暂停视频 * * @return 描述(只为举例需要) */ - (NSString *)pause; /** * 停止播放 * * @return 描述(只为举例需要) */ - (NSString *)stop; @end #import "LHPlayer.h" #import "LHPlayerProtocol.h" #import "LHAVPlayer.h" #import "LHIJKPlayer.h" @interface LHPlayer () { id<LHPlayerProtocol> player; } @end @implementation LHPlayer - (instancetype)initWithType:(EPlayerType)type { self = [super init]; if (self) { [self initPlayerWithType:type]; } return self; } // 初始化播放器 - (void)initPlayerWithType:(EPlayerType)type{ switch (type) { case EPlayerType_AVPlayer: { player = [[LHAVPlayer alloc] init]; break; } case EPlayerType_IJKPlayer: { player = [[LHIJKPlayer alloc] init]; break; } } } //开启视频 - (NSString *)play{ return [player lh_play]; } //暂停视频 - (NSString *)pause{ return [player lh_pause]; } //停止播放 - (NSString *)stop{ return [player lh_stop]; } @end
下面看客户端的调用。
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end #import "ViewController.h" #import "LHPlayer.h" @interface ViewController () { LHPlayer *player; } @property (weak, nonatomic) IBOutlet UIButton *btnAVPlayer; @property (weak, nonatomic) IBOutlet UIButton *btnIjkplayer; @property (weak, nonatomic) IBOutlet UILabel *lbState; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initPlayerWithType:EPlayerType_IJKPlayer]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } // 初始化播放器 - (void)initPlayerWithType:(EPlayerType)type{ if (player) { player = nil; } player = [[LHPlayer alloc] initWithType:type]; } #pragma mark - #pragma makr Button Event // 选择AVPlayer - (IBAction)btnAVPlayerEvent:(UIButton *)sender { sender.selected = YES; _btnIjkplayer.selected = NO; [self initPlayerWithType:EPlayerType_AVPlayer]; } // 选择Ijkplayer - (IBAction)btnIjkplayerEvent:(UIButton *)sender { sender.selected = YES; _btnAVPlayer.selected = NO; [self initPlayerWithType:EPlayerType_IJKPlayer]; } // 播放器播放视频 - (IBAction)btnPlayerEvent:(UIButton *)sender { _lbState.text = player ? [player play] : @"播放器为空"; } // 播放器暂停视频 - (IBAction)btnPauseEvent:(UIButton *)sender { _lbState.text = player ? [player pause] : @"播放器为空"; } // 播放器停止视频 - (IBAction)btnStopEvent:(UIButton *)sender { _lbState.text = player ? [player stop] : @"播放器为空"; } @end
例2、switch,if-else之类的分支语句,此类语句给人的直观感觉是判断条件明确,代码层次清晰,缺点可能是代码繁琐,杂乱无章,而且拆分困难。特别是到后期维护代码的时候,这种状况往往令人有食之无味,弃之可惜的感觉。使用策略模式可以代替switch或if-else之类的代码。
举个例子,以下是小明的计划安排:
周一打篮球
周二逛街
周三洗衣服
周四打游戏
周五唱歌
其他休息
借助策略模式我们可以这样实现代码:
@interface XiaoMing : NSObject - (void)doSomethingWithDayStr:(NSString *)dayStr params:(NSDictionary *)paramsDict; @end
#import "XiaoMing.h" @interface XiaoMing() @property(nonatomic,copy)NSDictionary *strategyDict;//策略 @property(nonatomic,copy)NSDictionary *paramDict;//参数 @end @implementation XiaoMing - (void)doSomethingWithDayStr:(NSString *)dayStr params:(NSDictionary *)paramsDict{ self.paramDict = paramsDict; if (self.strategyDict[dayStr]){ NSInvocation *doWhat = self.strategyDict[dayStr]; [doWhat invoke]; }else{ [self sleep]; } } - (NSInvocation *)invocationWithMethod:(SEL)selector{ NSMethodSignature*signature = [[self class] instanceMethodSignatureForSelector:selector]; if (signature == nil) { NSString *reason = [NSString stringWithFormat:@"提示:The method[%@] is not find", NSStringFromSelector(selector)]; @throw [NSException exceptionWithName:@"错误" reason:reason userInfo:nil]; } NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature]; invocation.target = self; invocation.selector = selector; NSDictionary *param = self.paramDict; //index表示第几个参数,注意0和1已经被占用了(self和_cmd),所以我们传递参数的时候要从2开始。 [invocation setArgument:&(param) atIndex:2]; return invocation; } - (void)playBasketball:(NSDictionary *)dict{ NSLog(@"方法:%s 参数:%@",__FUNCTION__,dict); } - (void)shopping:(NSDictionary *)dict{ NSLog(@"方法:%s 参数:%@",__FUNCTION__,dict); } - (void)washClothes:(NSDictionary *)dict{ NSLog(@"方法:%s 参数:%@",__FUNCTION__,dict); } - (void)playGames:(NSDictionary *)dict{ NSLog(@"方法:%s 参数:%@",__FUNCTION__,dict); } - (void)sing:(NSDictionary *)dict{ NSLog(@"方法:%s 参数:%@",__FUNCTION__,dict); } - (void)sleep{ NSLog(@"这是其他情况:%s",__FUNCTION__); } - (NSDictionary *)strategyDict{ if (_strategyDict == nil) { _strategyDict = @{ @"day1" : [self invocationWithMethod:@selector(playBasketball:)], @"day2" : [self invocationWithMethod:@selector(shopping:)], @"day3" : [self invocationWithMethod:@selector(washClothes:)], @"day4" : [self invocationWithMethod:@selector(playGames:)], @"day5" : [self invocationWithMethod:@selector(sing:)] }; } return _strategyDict; } @end
外部调用可以完全不再使用if-else
的判断了。
XiaoMing *xm = [[XiaoMing alloc]init]; //各种情况直接赋值给dayStr即可。 NSString *dayStr = @"day3"; [xm doSomethingWithDayStr:dayStr params:@{@"key":@"test"}];
来源:https://www.cnblogs.com/dhui69/p/9389806.html