每天一个设计模式之策略模式

什么是“策略模式”

策略模式是一种比较简单的模式,也叫做政策模式。
他的定义如下:
定义一组算法,将每个算法都封装起来,并且使他们可以互换。

那么,到底什么是策略模式呢?(概念和优缺点在文末,不想看例子的小伙伴可以直接跳到文末)
我们来举个例子:我们有一款游戏,游戏有四种角色:射手、刺客、狂战士、剑士, 同时也有四种武器可以提供角色进行切换和攻击,但是每次只能使用一种武器。
通过上面这段描述,学习过面向对象的我们可以很轻易地使用继承和抽象设计出以下类

1
2
3
4
    //角色的抽象类
public abstract class Role {
public abstract void fight();
}

然后分别新建四个类,然后继承Role,再分别实现对应的抽象方法, 在抽象方法中使用具体的武器,这么做确实是可以的。但是我们可以想想,我们现在只有四个武器,假如我们出现了十几个甚至上百个武器的时候,我们可能需要修改fight方法十几次甚至上百次,这将会产生多大的工作量。

这个时候, 策略模式就派上用场了:
我们可以将四种武器提取出来,封装成一个接口WeaponInterface, 然后再分别新建四个武器类实现这个接口。

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
//武器接口
public interface WeaponInterface {
public void userWeapon();
}

public class KnifeWeapon implements WeaponInterface {
@Override
public void userWeapon() {
System.out.println("使用匕首进行攻击");
}
}

public class BowAndArrowWeapon implements WeaponInterface {
@Override
public void userWeapon() {
System.out.println("使用弓箭进行攻击");
}
}

public class AxeWeapon implements WeaponInterface {
@Override
public void userWeapon() {
System.out.println("使用斧头进行攻击");
}
}

public class SwordWeapon implements WeaponInterface {
@Override
public void userWeapon() {
System.out.println("使用宝剑进行攻击");
}
}

这样一来,武器就封装好了。那么怎么使用呢?
我们可以在Role抽象类中添加这个武器的接口,并且添加setWeaponInterface的方法

1
2
3
4
5
6
7
8
9
    //角色的抽象类
public abstract class Role {
WeaponInterface weapon;
public abstract void fight();

public void setWeaponInterface(WeaponInterface weaponInterface) {
this.weaponInterface = weaponInterface;
}
}

当创建一个角色的时候,只需要实现Role抽象类即可。

1
2
3
4
5
6
7
8
9
10
11
12
public class ShooterRole extends Role {
public ShooterRole() {
//设置默认的武器
weaponInterface = new KnifeWeapon();
}

@Override
public void fight() {
System.out.print("我是射手,我");
weaponInterface.userWeapon();
}
}

接下来,我们就可以进行测试了:

1
2
3
4
5
6
7
8
9
public class Test {

public static void main(String[] args){
Role role = new ShooterRole();
role.fight();
role.setWeaponInterface(new AxeWeapon());
role.fight();
}
}

输出结果为:

1
2
我是射手,我使用匕首进行攻击
我是射手,我使用斧头进行攻击

到此为止,我们已经实现了武器的动态切换了,同时我们假如添加了其他武器,我们也就不需要每次都去修改fight方法了,只需要使用setWeaponInterface方法就可以动态地切换武器。

那么,概念来了:
策略模式使用的就是面向对象的继承和多态机制,它有三个策略角色,分别是:

  • 封装角色:例子中的Role或者是射手
  • 抽象策略角色:武器的接口。策略、算法家族的抽象,通常为接口。
  • 具体策略角色:各类武器(武器接口的具体实现)。实现抽象策略中的操作,含有具体的算法。

优点:

  1. 算法可以自由切换(武器可以自由切换)。
  2. 扩展性好。(增加一个武器的时候只需要实现接口就行)
  3. 避免使用多重判断语句。(切换武器)

缺点:

  1. 策略类数量增多。(增加一个武器就需要增加一个类,并且复用的可能性很小)
  2. 所有策略都必须对外暴露。(要使用一个武器,必须要知道有这个武器,了解这个武器。)这个缺点可以使用其他模式来进行修正,比如工厂方法模式、代理模式等等。

感谢阅读本博客。

欢迎关注我的博客:https://li-weijian.github.io/

欢迎关注我的CSDN:https://blog.csdn.net/qq352642663

需要联系请加QQ:352642663

欢迎联系我共同交流