什么是“策略模式”
策略模式是一种比较简单的模式,也叫做政策模式。
他的定义如下:
定义一组算法,将每个算法都封装起来,并且使他们可以互换。
那么,到底什么是策略模式呢?(概念和优缺点在文末,不想看例子的小伙伴可以直接跳到文末)
我们来举个例子:我们有一款游戏,游戏有四种角色:射手、刺客、狂战士、剑士, 同时也有四种武器可以提供角色进行切换和攻击,但是每次只能使用一种武器。
通过上面这段描述,学习过面向对象的我们可以很轻易地使用继承和抽象设计出以下类
//角色的抽象类
public abstract class Role {
public abstract void fight();
}
然后分别新建四个类,然后继承Role,再分别实现对应的抽象方法, 在抽象方法中使用具体的武器,这么做确实是可以的。但是我们可以想想,我们现在只有四个武器,假如我们出现了十几个甚至上百个武器的时候,我们可能需要修改fight方法十几次甚至上百次,这将会产生多大的工作量。
这个时候, 策略模式就派上用场了:
我们可以将四种武器提取出来,封装成一个接口WeaponInterface, 然后再分别新建四个武器类实现这个接口。
//武器接口
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的方法
//角色的抽象类
public abstract class Role {
WeaponInterface weapon;
public abstract void fight();
public void setWeaponInterface(WeaponInterface weaponInterface) {
this.weaponInterface = weaponInterface;
}
}
当创建一个角色的时候,只需要实现Role抽象类即可。
public class ShooterRole extends Role {
public ShooterRole() {
//设置默认的武器
weaponInterface = new KnifeWeapon();
}
@Override
public void fight() {
System.out.print("我是射手,我");
weaponInterface.userWeapon();
}
}
接下来,我们就可以进行测试了:
public class Test {
public static void main(String[] args){
Role role = new ShooterRole();
role.fight();
role.setWeaponInterface(new AxeWeapon());
role.fight();
}
}
输出结果为:
我是射手,我使用匕首进行攻击
我是射手,我使用斧头进行攻击
到此为止,我们已经实现了武器的动态切换了,同时我们假如添加了其他武器,我们也就不需要每次都去修改fight方法了,只需要使用setWeaponInterface方法就可以动态地切换武器。
那么,概念来了:
策略模式使用的就是面向对象的继承和多态机制,它有三个策略角色,分别是:
- 封装角色:例子中的Role或者是射手
- 抽象策略角色:武器的接口。策略、算法家族的抽象,通常为接口。
- 具体策略角色:各类武器(武器接口的具体实现)。实现抽象策略中的操作,含有具体的算法。
优点:
- 算法可以自由切换(武器可以自由切换)。
- 扩展性好。(增加一个武器的时候只需要实现接口就行)
- 避免使用多重判断语句。(切换武器)
缺点:
- 策略类数量增多。(增加一个武器就需要增加一个类,并且复用的可能性很小)
- 所有策略都必须对外暴露。(要使用一个武器,必须要知道有这个武器,了解这个武器。)这个缺点可以使用其他模式来进行修正,比如工厂方法模式、代理模式等等。