用23种设计模式打造一个cocos creator的游戏框架----(十一)桥接模式

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)

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值