1、模式标准
模式名称:策略模式
模式分类:行为型
模式意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。此模式使得算法可以独立于使用它们的客户而变化
结构图:
适用于:
1、许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
2、需要使用一个算法的不同变体。例如,定义一些反映不同空间的空间/时间权衡的算法当这些变体实现为一个算法的类层次时,可以使用策略模式。
3、算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4、一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的 Strategy 类中,以代替这些条件语句。
2、分析与设计
策略和桥接模式看起来可能非常相似,但策略模式是行为型,桥接模式是结构型。策略模式是直接引用实现类,而桥接模式是引用一个实现类的接口。当前策略模式关键是可以相互替换算法。接下来把我们曾经用过的武器替换来举例,修改一下我们的意图
意图:定义一系列的算法(武器),把它们一个个封装起来,并且使它们可以相互替换。
3、开始打造
// 武器接口
export interface IWeapon {
useWeapon(): void;
}
// 剑
export class Sword implements IWeapon {
useWeapon(): void {
console.log("用剑进行攻击");
}
}
// 斧头
export class Axe implements IWeapon {
useWeapon(): void {
console.log("用斧头进行攻击");
}
}
// 弓
export class Bow implements IWeapon {
useWeapon(): void {
console.log("用弓箭进行攻击");
}
}
// 近程攻击
export class MeleeAttack implements IAttackStrategy {
attack(weapon: IWeapon): void {
console.log("进行近程攻击:");
weapon.useWeapon();
}
}
【优化】结合前面的桥接模式的攻击方式,我们将攻击系统升级一下
// 攻击方式接口
export interface IAttackStrategy {
attack(weapon: IWeapon): void;
}
// 近程攻击
export class MeleeAttack implements IAttackStrategy {
attack(weapon: IWeapon): void {
console.log("进行近程攻击:");
weapon.useWeapon();
}
}
// 远程攻击
export class RangedAttack implements IAttackStrategy {
attack(weapon: IWeapon): void {
console.log("进行远程攻击:");
weapon.useWeapon();
}
}
// 武器接口
export interface IWeapon {
useWeapon(): void;
}
// 剑
export class Sword implements IWeapon {
useWeapon(): void {
console.log("用剑进行攻击");
}
}
// 斧头
export class Axe implements IWeapon {
useWeapon(): void {
console.log("用斧头进行攻击");
}
}
// 弓
export class Bow implements IWeapon {
useWeapon(): void {
console.log("用弓箭进行攻击");
}
}
// 抽象战斗者
export abstract class Fighter {
protected attackStrategy: IAttackStrategy;
protected weapon: IWeapon;
constructor(attackStrategy: IAttackStrategy, weapon: IWeapon) {
this.attackStrategy = attackStrategy;
this.weapon = weapon;
}
attack(): void {
this.attackStrategy.attack(this.weapon);
}
// 更换武器的方法
setWeapon(weapon: IWeapon): void {
this.weapon = weapon;
}
}
// 骑兵
export class Cavalry extends Fighter {
constructor(attackStrategy: IAttackStrategy, weapon: IWeapon) {
super(attackStrategy, weapon);
}
}
// 弓箭手
export class Archer extends Fighter {
constructor(attackStrategy: IAttackStrategy, weapon: IWeapon) {
super(attackStrategy, weapon);
}
}
4、开始使用
export class UnitItem extends Component implements IItem, IUnitItem {
ad: number = 100;
mp: number = 0;
role: Fighter;
private currentState: IUnitState = null;
accept(visitor: IAttackVisitor) {
visitor.visitUnitItem(this)
}
setRole(role: Fighter): void {
this.role = role;
}
setWeapon(weapon: IWeapon) {
this.role.setWeapon(weapon)
}
.....
}
let unitItem001 = xhgame.itemFactory.createUnitItem('kuloubing', UnitType.UnitSpine)
let unitItem002 = xhgame.itemFactory.createUnitItem('kuloubing', UnitType.UnitSpine)
unitItem001.idle()
unitItem002.idle()
const sword = new Sword();
const bow = new Bow();
const axe = new Axe();
unitItem001.setRole(new Cavalry(new MeleeAttack(), sword));
console.log('unitItem001(骑兵-近程)使用【剑】对unitItem002发起了攻击')
unitItem001.attack(unitItem002)
// 更换骑兵的武器为斧头
unitItem001.setWeapon(axe);
console.log('unitItem001(骑兵-近程)使用【斧头】对unitItem002发起了攻击')
unitItem001.attack(unitItem002);
unitItem002.setRole(new Cavalry(new RangedAttack(), bow));
console.log('unitItem002(骑兵-远程)使用【弓】对unitItem001发起了攻击')
unitItem002.attack(unitItem001)
总结:桥接模式在构建时定好攻击方式,策略模式在行为中使用不同的武器。