频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
策略模式
2016-11-12 10:51:00         来源:weimeng809的专栏  
收藏   我要投稿

1、策略模式的定义
定义了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

2、策略模式的简要概述
策略模式的核心是策略类。一种具体的策略相当于一个具体的解决问题的方法,这些方法一般可以看作是一些算法,这些算法可以相互替换,是一种平行的结构,它们有一个抽象的策略类,该类中定义了一个接口,这些具体的策略类都实现这个接口。这样对于使用该策略类的客户来说,耦合性就很小。这些使用策略类的客户有一个策略类,通过该策略类提供的接口,来帮助它完成一些特定的功能。这样比将这些实现特定功能的代码放在客户类中更好。即使你将这些实现特定功能的代码(算法方法)抽象到客户类的父类中,也是没有这种策略模式实现起来灵活,原因在于策略模式客户类和策略类之间的关系是HAS-A(有一个)的关系,它们之间相当于使用对象组合来完成一个任务或者功能。而将特定功能放在客户类的父类中,这种方式是继承,继承的关系可以看作是IS-A(是一个)的关系。很显然HAS-A比IS-A的耦合性更小。对使用策略模式来说,改变一些算法或者添加一些新算法,对客户类的影响都是很小的。
下面看一个策略模式的结构图:
这里写图片描述
在上图中Context就相当于客户类。它根据自己的业务需要决定具体使用哪一种策略(ConcreteStrategyA,ConcreteStrategyB or ConcreteStrategyC)。<喎"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjOhosq508Ozob6wPGJyIC8+DQoxo6nSu7j2wODU2sbkstnX99bQyrnTw7bguPbM9bz+0+++5MC0tqjS5cHL0O224NDQzqqho87Sw8e/ydLUsNHP4LnYtcTM9bz+t9bWp9LGtq+1vcv8w8fX1Ly6tcSy38LUwODW0KGjPGJyIC8+DQoyo6m2qNLlwcvSu8+1wdDL47eotcSx5Mzlo6zV4tCpy+O3qMrHxr3Q0LXEveG5uaOsuPm+3dDo0qqyu82stcS5psTcv8nS1L340NDM5ru7oaM8YnIgLz4NCjOjqdDo0qq21Mvjt6i9+NDQt+LXsKOssrvP68jDv827p8DgudjQxNXi0KnL47eotcTKtc/Wo6i/ycTc09DSu9CpuLTU07XEy+O3qLrNyv2+3b3hubmjqaOssqLH0r+8wse1vdLUuvO/ycTcu+G21NXi0KnL47eovfjQ0MCp1bmjrLy0v8nE3NDOs8nSu7j2y+O3qLTYoaM8L3A+DQo8cD40oaKy38LUxKPKvb7ZwP08YnIgLz4NCrzZyejU2s7Sw8e1xNOm08PW0NKqyrnTw8XF0PLL47eoo6zS8s6qxcXQ8svjt6jT0LrctuCjrLb4x9K4+b7dsrvNrLXEx+m/9qOsztLDx7/JxNy74dGh1PGyu82stcTFxdDyy+O3qKGjscjI59PQ0KnKsbryztLDx9Do0qq/vMLHxcXQ8svjt6i1xM7ItqjQ1KGjPGJyIC8+DQrPwsPmz8i4+LP20ru49sDgzbw8YnIgLz4NCjxpbWcgYWx0PQ=="这里写图片描述" src="/uploadfile/Collfiles/20161111/20161111105103342.png" title="\" />
在这里YCSortAlgorithm是策略类,下面的两个子类是具体的策略类。这样功能就独立出来了,以后客户类需要用到排序的算法,拥有这个策略类的实例,调用其中的接口就可以了。而且对于策略类来说,它也有一定的可扩展性,可以扩充一些其他的排序算法。下面给出具体的代码。

YCSortAlgorithm.h文件

#import 
typedef NS_ENUM(NSUInteger, YCSortAlgorithmType) {
    YCSortAlgorithmBubble,
    YCSortAlgorithmSelect
};
@interface YCSortAlgorithm : NSObject
//工厂方法
+ (instancetype)sortAlgorithmWithSortType:(YCSortAlgorithmType)sortType;
//策略类对外提供的排序接口
- (void)performSortWithArray:(NSMutableArray *)array;
@end

YCSortAlgorithm.m文件

#import "YCSortAlgorithm.h"
#import "YCSelectSortAlgorithm.h"
#import "YCBubbleSortAlgorithm.h"

@interface YCSortAlgorithm ()
@property (nonatomic, strong) YCSortAlgorithm *sortAlgorithm;
@end

@implementation YCSortAlgorithm

+ (instancetype)sortAlgorithmWithSortType:(YCSortAlgorithmType)sortType {
    return [[self alloc] initSortAlgorithmWithSortType:sortType];
}

- (instancetype)initSortAlgorithmWithSortType:(YCSortAlgorithmType)sortType {
    if (self = [super init]) {

        switch (sortType) {
            case YCSortAlgorithmBubble:
                self.sortAlgorithm = [[YCSelectSortAlgorithm alloc] init];
                return self.sortAlgorithm;
            default:
                self.sortAlgorithm = [[YCBubbleSortAlgorithm alloc] init];
                return self.sortAlgorithm;
        }

    }
    return self;
}

- (void)performSortWithArray:(NSMutableArray *)array {
//    subclass should implement this method
}

@end

冒泡排序算法中YCBubbleSortAlgorithm.m文件

#import "YCBubbleSortAlgorithm.h"

@implementation YCBubbleSortAlgorithm

- (void)performSortWithArray:(NSMutableArray *)array {
    for (NSInteger i = 0; i < array.count; i++) {
        //array.count - i - 1为跑一趟,需要比较的次数
        for (NSInteger j = 0; j < array.count - i - 1; j++) {
            //如果后面的小于前面的那么就进行交换,这样排出来的结果就是升序的
            if (array[j+1] < array[j]) {
                NSNumber *temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}

@end

冒泡排序是一个稳定的排序算法。

选择排序中YCSelectSortAlgorithm.m文件的代码

#import "YCSelectSortAlgorithm.h"
@implementation YCSelectSortAlgorithm

- (void)performSortWithArray:(NSMutableArray *)array {
    for (NSInteger i = 0; i < array.count; i++) {
        //在一趟循环中a[i]中,存放的是最小的值,当第一趟比较晚的时候,array[0]中存放的就是最小的值
        for (NSInteger j = i + 1; j < array.count; j++) {
            if (array[i] > array[j]) {
                NSNumber *temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
@end

选择排序是一个不稳定的排序算法。
对于客户类来说使用排序算法也是很简单的,如下:

NSMutableArray *arrayM = [NSMutableArray arrayWithObjects:@2, @5, @3, @11, @10, nil];
[[YCSortAlgorithm sortAlgorithmWithSortType:YCSortAlgorithmBubble] performSortWithArray:arrayM];
NSLog(@"--arrayM:%@---", arrayM);

这里用简单工厂方法创建了一个类簇,客户类可以不接触该策略类的具体子类,而使用其中具体子类所实现的具体功能。其实我们在UIKit中经常会碰到这种类簇模式,例如:UIButton就是一个类簇的例子。我们通过buttonWithType: 来实例化一个具体的UIButton实例,但是根据type的不同,这个类就是一个具体的UIButton子类类型。
在获得策略类的实例后,通过执行策略类提供的接口,执行相应的排序功能。
当然这里只是一个简单的例子,实现该功能也有很多其他的方法,在这里只是演示策略模式。

5、策略模式所体现的面向对象设计原则
1)找出应用中变化的地方,并把它和不变的部分独立出来。
2)针对接口编程,而不是针对实现编程。
3)多用组合,少用继承。

由于在上面所举的例子过于简单,可能没有很好的说明这些设计原则。下面在给出一些具体的解释和说明。
找出应用中变化的地方,并把它和不变的部分独立出来。对于这一条,我们可以这样去想,如果将这些排序算法直接放在客户类中,也能够实现排序的需求,但是这一部分可能是变化的部分,例如,如果我们的需求变了,需要从排序算法的稳定性方面考虑,将不稳定的排序算法替换为稳定性的排序算法。那么我们就需要再改动这一部分的代码。而且对于算法来说,就相当于是一个工具性的函数(给我一个输入,我给你一个输出)。因此我们需要将这一可复用,也可能在客户类中需要变化的部分独立出来。
针对接口编程,而不是针对实现编程。 在我们的客户类中我们还可以建立一个策略类的引用。这个策略类直接调用策略类所提供的接口。策略类是什么具体型的策略类我们并不关心,我们只是知道它能调用策略类所提供的接口实现排序的功能。

//sortAlgorithm是一个YCSortAlgorithm类型
//通过参数type,我们知道sortAlgorithm的实际类型是YCBubbleSortAlgorithm
self.sortAlgorithm = [YCSortAlgorithm sortAlgorithmWithSortType:YCSortAlgorithmBubble] ;
    [self.sortAlgorithm performSortWithArray:arrayM];

多用组合,少用继承。 关于这一点,可以理解为描述客户类和策略类直接的关系。我们可以看到客户类和策略类是一种对象组合的模式。在客户类中有一个策略类的实例(HAS-A),而不是将这些排序类的功能抽取到客户类的父类中,通过继承的方式来使用(IS-A)。这样做的好长是这些排序功能独立出来以后,可复用性更强。
这些设计原则其实不只是策略模式所独有的,在其他的模式中也是有这些设计原则的影子的。

点击复制链接 与好友分享!回本站首页
相关TAG标签 策略模式
上一篇:启动图和Icon的设置
下一篇:卷积码维特比译码算法的FPGA实现(初步)
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站