设计模式------策略模式

举个栗子

考虑一个car类,有个brake(制动)方法,多个汽车模型可能拥有几种不同的制动行为。
方案一:由于制动行为在模型间频繁变化,通常的方法是通过继承来实现,在子类中实现这些行为。这种方法有很大的缺点:

  1. 必须在每个模型中实现制动行为,各个汽车模型之间存在大量重复代码(不同汽车模型的制动行为可能是一样的)。
  2. 汽车的模型与制动行为的实现耦合在一起,如果某种制动行为发生变化或新增一个制动行为,那么对应的所有汽车模型就要修改,不符合“封装变化原则”与“开闭原则”。
  3. 随着汽车模型数量的增加,管理制动行为的成本大大增加。如,对于所有x种汽车模型都要稍微修改一下制动行为。
    我们发现,当涉及到“维护”时,以复用为目的的继承,解决并不完美。

方案二:将制动行为封装进一组行为类中,通过组合动态设定汽车模型对应的制动行为。当有制动行为修改或有新的制动行为我们可以操纵行为类,将行为类的实现与汽车模型分离,减少耦合度。

上述方案即为策略模式,让行为(算法)和对象分开来,使得行为(算法)可以独立于它的客户的变化。

定义

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

汽车模型的实现

行为类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//定义制动行为接口makeBrake,.m文件里没有任何实现 
@interface BrakeBehavior : NSObject
-(void)makeBrake;
@end

//继承自BrakeBehavior 实现makeBrake接口为NormalBrake
@interface NormalBrake : BrakeBehavior
@end

@implementation NormalBrake

-(void)makeBrake{
NSLog(@"make brake With NormalBrake");
}

@end

//继承自BrakeBehavior 实现makeBrake接口为ABSBrake
@interface ABSBrake : BrakeBehavior
@end

@implementation ABSBrake

-(void)makeBrake{
NSLog(@"make brake With ABSBrake");
}

@end

汽车模型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//Car模型基类,通过组合绑定制动行为
@interface Car : NSObject

@property(nonatomic,strong)BrakeBehavior * brake;
-(void)performBrake;

@end

@implementation Car

-(void)performBrake{
[self.brake makeBrake];
}
@end

//Sedan模型,默认制动行为NormalBrake
@interface Sedan : Car
@end

@implementation Sedan

-(instancetype)init{
self = [super init];
if (self) {
self.brake = [NormalBrake new];
}
return self;
}

@end

//SUV模型,默认制动行为ABSBrake
@interface SUV : Car
@end

@implementation SUV

-(instancetype)init{
self = [super init];
if (self) {
self.brake = [ABSBrake new];
}
return self;
}

@end

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
-(void)testForCar{

Car * sedanCar = [Sedan new];
[sedanCar performBrake];//NormalBrake

Car * suvCar = [SUV new];
[suvCar performBrake];//ABSBrake

//动态改变sendanCar的制动行为为ABSBrake
sedanCar.brake = [ABSBrake new];
[sedanCar performBrake];
}

分析

通过UML类图分析汽车模型实现:

  • BrakeBehavior :策略类基类,声明相应策略方法。
  • NormalBrake、ABSBrake:具体策略类,实现具体的策略方法。
  • Car:上下文类,持有具体的策略类实例,并负责调用相关策略。
  • Sedan、SUV:具体的上下文实例类,持有对应默认策略类实例。

策略模式的优点

  • 提供使用组合替代继承的方案,将策略(制动行为)的实现从客户(汽车模型)中解耦。
  • 符合“开-闭原则”,可以在不修改原有系统基础上选择策略。
  • 易于拓展,可以灵活的增加新策略。

缺点

  • 维护多个策略类给开发带来额外开销。
  • 调用者(上下文类)必须知道所有策略类,并自行决定使用哪一个策略类。

总结

策略模式本质是面向对象中的继承和多态。策略模式主要用于将策略(算法、行为)的定义与使用策略的上下文分开,达到策略实现与客户(上下文)解耦的目的。

如果对你有帮助的话,Star✨下一吧!