设计模式整理(6) 策略模式
2019-02-13 本文已影响0人
安静的蓝孩子
学习《Android 源码设计模式解析与实践》系列笔记
介绍
通常如果一个问题有多种解决方案时,我们会根据不同的场景选择不同的解决方案。而最简单的实现,是利用 if-else 或者 switch-case。但是这样实现的代码耦合性太高、代码臃肿,维护成本大。策略模式能很好的解决这些问题。
定义
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
使用场景
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时(在运行时动态选择具体要执行的行为)。
- 对客户隐藏具体策略(算法)的实现细节,需要安全地封装多种同一类型的操作。
- 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
结构
策略模式 UML 图=0&size=c710_u400&quality=100&vuk=-&ft=video)
- Context : 用来操作策略模式的上下文环境
- Stragety : 策略的抽象类
- ConcreteStragety : 策略的具体实现
实现
在射击游戏中,游戏英雄刚开始使用的是手枪,随着等级的提高,会升级为步枪、冲锋枪,甚至是人民币玩家还有豪华的狙击枪巴雷特等。玩家可以根据需要给人物切换枪,然而不管怎么切换,最后的行为都是一样的,那就是拿枪射击。
Stragety 部分
/**
* 枪的抽象类,对应 Strategy 角色
*/
public abstract class Gun {
public abstract void fire();
}
/**
* 手枪类,对应 ConcreteStrategy 角色
*/
public class HandGun extends Gun {
@Override
public void fire() {
System.out.println("使用手枪射击");
}
}
/**
* 步枪类,对应 ConcreteStrategy 角色
*/
public class Musket extends Gun {
@Override
public void fire() {
System.out.println("使用步枪射击");
}
}
/**
* 冲锋枪类,对应 ConcreteStrategy 角色
*/
public class SubMachineGun extends Gun {
@Override
public void fire() {
System.out.println("使用冲锋枪射击");
}
}
Context 部分
/**
* 游戏角色,对应 Context 角色,既策略的使用者
*/
public class Player {
private Gun mGun;
public void fire() {
if (mGun != null) {
mGun.fire();
}
}
public void setGun(Gun gun) {
this.mGun = gun;
}
}
整体调用
public class Client {
public static void main(String args[]) {
Player player = new Player();
Gun handGun = new HandGun();
player.setGun(handGun);
player.fire();
Gun musket = new Musket();
player.setGun(musket);
player.fire();
Gun subMachineGun = new SubMachineGun();
player.setGun(subMachineGun);
player.fire();
}
}
log 输出
使用手枪射击
使用步枪射击
使用冲锋枪射击
Android 中的源码实现
Android 动画中的插值器(Interpolator)
总结
策略模式主要是用来分离算法,在相同的行为抽象下有不同的具体实现策略。
优点
- 结构清晰明了,使用简单直观
- 耦合度较低,扩展方便
缺点
- 随着策略的增多,子类也会变得繁多
相关文章:
设计模式整理(1) 代理模式
设计模式整理(2) 单例模式
设计模式整理(3) Builder 模式
设计模式整理(4) 原型模式
设计模式整理(5) 工厂模式
设计模式整理(6) 策略模式
设计模式整理(7) 状态模式
设计模式整理(8) 责任链模式
设计模式整理(9) 观察者模式
设计模式整理(10) 适配器模式
设计模式整理(11) 装饰模式
设计模式整理(12) 中介者模式