1、模式标准
模式名称:桥接模式
模式分类:结构型
模式意图:将抽象部分与其实现部分分离,使它们都可以独立地变化。
结构图:
适用于:
1、不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
2、类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这是 Bridge 模式使得开发者可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
3、对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译
4、想在多个对象间共享实现 (可能使用引用计数),但同时要求客户并不知道这一点
主要成员:
- 抽象类(Abstraction):定义和保存客户端的引用,维护与实现对象之间的关联关系。
- 扩展抽象类(Refined Abstraction):扩展和精化抽象类中的接口定义。
- 实现类接口(Implementor):定义实现类的接口,可以与抽象类的接口相互独立。
- 具体实现类(Concrete Implementor):具体实现接口,在不同的实现类中提供基本操作的不同实现。
2、分析与设计
桥接模式,通俗点讲就如同嫁接,比如有一个树,会开花结果,我给它嫁接苹果枝,在开花结果后,长的是苹果。如果嫁接橘子枝,在开花结果后,长的是橘子。
当前的例子用在攻击者使用武器中的攻击功能。攻击者使用武器中的攻击方法作为抽象方法,具体如何攻击需要武器来实现,武器作为一个独立的存在,具有攻击功能外还具有售卖功能。我们直接桥接了其中的攻击方法。桥接和策略在某些方法上有些像,但是桥接模式与策略模式的差异之处在于,桥接只是桥接了其中的一个或几个方法,而策略模式是替换了整个策略算法。
意图:将抽象部分(攻击)与其实现部分(剑攻击和弓攻击)分离,使它们都可以独立地变化(剑除了攻击方法之外还有售卖等其他功能,当前只是桥接了攻击功能)。
3、开始打造
// 战斗方式
export abstract class Fighter {
// protected attackStrategy: IAttackStrategy;
protected weapon: IWeapon;
constructor(weapon: IWeapon) {
this.weapon = weapon;
}
// 设计模式,桥接模式
// 使用了武器里面的攻击方法(武器可能还有售卖的方法,且是独立)
attack(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>): void {
this.weapon.attack(fromUnitItem, toUnitItem);
}
// 更换武器
setWeapon(weapon: IWeapon): void {
this.weapon = weapon;
}
abstract getType(): string
}
// 普通攻击者
export class NormalFighter extends Fighter {
constructor(weapon: IWeapon) {
super(weapon);
}
getType(): string {
return 'NormalFighter' + '' // todo weapon
}
}
// 武器(单位攻击属性)接口
export interface IWeapon {
attackStrategy: IAttackStrategy
price: number
sell(): number
getEffect(): string;
attack(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>): void
setAttackStrategy(attackStrategy: IAttackStrategy): void
}
export abstract class Weapon implements IWeapon {
attackStrategy: IAttackStrategy
price: number
itemNo: string
constructor(attackStrategy: IAttackStrategy, price: number, itemNo: string) {
this.attackStrategy = attackStrategy
this.price = price
this.itemNo = itemNo
}
sell(): number {
return this.price
}
getEffect(): string {
return this.itemNo
}
// 攻击者的抽象attack方法桥接到了此处武器的attack方法
attack(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>): void {
// 武器的attack实现,用具体攻击策略实现
this.attackStrategy.doAction(fromUnitItem, toUnitItem, this.getEffect())
}
setAttackStrategy(attackStrategy: IAttackStrategy) {
this.attackStrategy = attackStrategy
}
}
// 剑
export class Sword extends Weapon {
constructor(ItemNo: string) {
super(new MeleeAttack(), 100, ItemNo)
}
}
// 斧头
export class Axe extends Weapon {
constructor(ItemNo: string) {
super(new MeleeAttack(), 100, ItemNo)
}
}
// 弓
export class Bow extends Weapon {
constructor(ItemNo: string) {
super(new RangedAttack(), 100, ItemNo)
}
}
4、开始使用
单位
export class UnitItem extends Component implements IItem, IUnitItem {
ad: number = 100;
mp: number = 0;
// 攻击方法
fighter: Fighter;
private currentState: IUnitState = null;
.....
setFighter(fighter: Fighter): void {
this.fighter = fighter;
}
}
// 设计模式:享元模式
// 运用共享技术有效地支持大量细粒度的对象
export class FlyweightFactory {
// 攻击访问者s(伤害计算系统)
private attackVisitors: { [key: string]: IAttackVisitor } = {};
// 单位攻击方式方法
private fighters: { [key: string]: Fighter } = {};
。。。。。
public getFighter(key: string): Fighter {
if (!this.fighters[key]) {
switch (key) {
case FighterType.Jianbing:
this.fighters[key] = new NormalFighter(new Sword('bbc'));
break;
case FighterType.Gongbing:
this.fighters[key] = new NormalFighter(new Bow('bbc'));
break;
default:
throw new Error('无效的FighterType');
}
}
return this.fighters[key];
}
}
简单示例
let unitItem001 = xhgame.itemFactory.createUnitItem('shibing_001')
let unitItem002 = xhgame.itemFactory.createUnitItem('shibing_002')
unitItem001.setFighter(xhgame.flyweightFactory.getFighter(FighterType.Jianbing));
unitItem002.setFighter(xhgame.flyweightFactory.getFighter(FighterType.Jianbing));
console.log('unitItem001对unitItem002发起了攻击')
unitItem001.attack(unitItem002)
console.log('unitItem002对unitItem001发起了攻击')
unitItem002.attack(unitItem001)