举个栗子
考虑一个car类,有个brake(制动)方法,多个汽车模型可能拥有几种不同的制动行为。
方案一:由于制动行为在模型间频繁变化,通常的方法是通过继承来实现,在子类中实现这些行为。这种方法有很大的缺点:
- 必须在每个模型中实现制动行为,各个汽车模型之间存在大量重复代码(不同汽车模型的制动行为可能是一样的)。
- 汽车的模型与制动行为的实现耦合在一起,如果某种制动行为发生变化或新增一个制动行为,那么对应的所有汽车模型就要修改,不符合“封装变化原则”与“开闭原则”。
- 随着汽车模型数量的增加,管理制动行为的成本大大增加。如,对于所有x种汽车模型都要稍微修改一下制动行为。
我们发现,当涉及到“维护”时,以复用为目的的继承,解决并不完美。
方案二:将制动行为封装进一组行为类中,通过组合动态设定汽车模型对应的制动行为。当有制动行为修改或有新的制动行为我们可以操纵行为类,将行为类的实现与汽车模型分离,减少耦合度。
上述方案即为策略模式,让行为(算法)和对象分开来,使得行为(算法)可以独立于它的客户的变化。
定义
策略模式:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
汽车模型的实现
行为类
1 | //定义制动行为接口makeBrake,.m文件里没有任何实现 |
汽车模型类
1 | //Car模型基类,通过组合绑定制动行为 |
测试代码
1 | -(void)testForCar{ |
分析
通过UML类图分析汽车模型实现:
- BrakeBehavior :策略类基类,声明相应策略方法。
- NormalBrake、ABSBrake:具体策略类,实现具体的策略方法。
- Car:上下文类,持有具体的策略类实例,并负责调用相关策略。
- Sedan、SUV:具体的上下文实例类,持有对应默认策略类实例。
策略模式的优点
- 提供使用组合替代继承的方案,将策略(制动行为)的实现从客户(汽车模型)中解耦。
- 符合“开-闭原则”,可以在不修改原有系统基础上选择策略。
- 易于拓展,可以灵活的增加新策略。
缺点
- 维护多个策略类给开发带来额外开销。
- 调用者(上下文类)必须知道所有策略类,并自行决定使用哪一个策略类。
总结
策略模式本质是面向对象中的继承和多态。策略模式主要用于将策略(算法、行为)的定义与使用策略的上下文分开,达到策略实现与客户(上下文)解耦的目的。
如果对你有帮助的话,Star✨下一吧!