策略模式
定义:
将类中经常改变或者可能改变的部分提取为作为一个抽象策略接口类,然后在类中包含这个对象的实例,这样类实例在运行时就可以随意调用实现了这个接口的类的行为。
比如定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换,使得算法可独立于使用它的客户而变化,这就是策略模式。
应用场景:
应用程序需要实现特定的功能服务,而该程序有多种实现方式使用,所以需要动态地在几种算法中选择一种。
一个类定义了多种行为算法,并且这些行为在类的操作中以多个条件语句的形式出现,就可以将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。
优点:
可以动态改变对象的行为。
结构:
1)环境类(Context):通过 ConcreteStrategy 具体策略类来配置,持有 Strategy 对象并维护对Strategy 对象的引用。可定义一个接口来让 Strategy 访问它的数据。
2)抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy 定义的算法。
3)具体策略类(ConcreteStrategy): Strategy 接口的具体算法。
代码示例:
我们以植物大战里的僵尸为例,每个僵尸都有不同的外观,不同的移动方式,不同的攻击方式。但是它们都具备外观、移动、攻击特征。
package com.test;
public class StrategicMode {
public static void main(String[] args) {
// 普通僵尸
Zombie normalZombie = new NormalZombie();
normalZombie.display();
normalZombie.move();
normalZombie.attack();
// 跳跳僵尸
Zombie pogoZombie = new PogoZombie();
pogoZombie.display();
pogoZombie.move();
pogoZombie.attack();
// 可以在运行的时候修改跳跳僵尸的移动方式,比如跳跳僵尸被植物攻击,移动方式变为一步一步移动
pogoZombie.setMove(new StepByStepMove());
System.out.println("跳跳僵尸被植物攻击,移动方式发生了变化。");
pogoZombie.move();
}
}
// 抽象移动方式
interface Move{
void move();
}
// 抽象攻击方式
interface Attack{
void attack();
}
// 定义一步一步移动方式
class StepByStepMove implements Move{
public void move() {
System.out.println("移动方式:一步一步移动...");
}
}
// 定义跳移动方式
class JumpMove implements Move{
public void move() {
System.out.println("移动方式:跳...");
}
}
// 定义咬攻击方式
class BiteAttack implements Attack{
public void attack() {
System.out.println("攻击方式:咬...");
}
}
// 抽象僵尸模型
abstract class Zombie{
Move move;
Attack attack;
public Zombie(Move move, Attack attack) {
this.move = move;
this.attack = attack;
}
abstract void display();
abstract void move();
abstract void attack();
public Move getMove() {
return move;
}
public void setMove(Move move) {
this.move = move;
}
public Attack getAttack() {
return attack;
}
public void setAttack(Attack attack) {
this.attack = attack;
}
}
// 普通僵尸
class NormalZombie extends Zombie{
public NormalZombie(){
super(new StepByStepMove(),new BiteAttack());
}
public NormalZombie(Move move, Attack attack) {
super(move, attack);
}
@Override
void display() {
System.out.println("普通僵尸...");
}
@Override
void move() {
super.move.move();
}
@Override
void attack() {
super.attack.attack();
}
}
// 跳跳僵尸
class PogoZombie extends Zombie{
public PogoZombie(){
super(new JumpMove(),new BiteAttack());
}
public PogoZombie(Move move, Attack attack) {
super(move, attack);
}
@Override
void display() {
System.out.println("跳跳僵尸...");
}
@Override
void move() {
super.move.move();
}
@Override
void attack() {
super.attack.attack();
}
}