桥接模式
定义
桥接模式即将抽象部分与它的实现部分分离开来,使他们都可以独立变化。
桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。
UML
理解
以上两句话结合桥接模式个人理解是这样的:
1.在抽象层面上,是抽象A和抽象B 关联/聚合
2.在具体实现上,抽象A可以独立拓展,而抽象B也可以独立拓展
举个例子:
1.角色(抽象A)和武器(抽象B),角色可以拥有一个或多个武器(关联/聚合)
2.角色可以拓展为矮人、人类、精灵等等
武器可以拓展为枪、弓箭、刀等等
在不使用桥接模式我们就需要定义矮人枪手、矮人弓箭手、矮人刀手、人类枪手、人类弓箭手…
而使用了桥接模式,我们只需要在角色和武器两个维度上独自变化就好
代码
两个抽象类
namespace DesignModel.Bridge
{
//抽象类A
public abstract class Abstraction
{
public Implementor implementor;
public abstract void Operation();
}
//抽象类B
public abstract class Implementor
{
public abstract void OperationImp();
}
}
对应的实现
namespace DesignModel.Bridge
{
//抽象类A的实现
public class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.OperationImp();
}
}
//抽象类B的实现
public class ConcreteImplementorA : Implementor
{
public override void OperationImp()
{
Debug.Log("ConcreteImplementor: A");
}
}
public class ConcreteImplementorB : Implementor
{
public override void OperationImp()
{
Debug.Log("ConcreteImplementor: B");
}
}
}
Client测试
using DesignModel.Bridge;
public class Client_Bridge : MonoBehaviour
{
void Start ()
{
Abstraction abstraction = new RefinedAbstraction();
abstraction.implementor = new ConcreteImplementorA();
abstraction.Operation();
abstraction.implementor = new ConcreteImplementorB();
abstraction.Operation();
}
}
测试结果
桥接模式和工厂结合
桥接模式是两个维度变化的模式,抽象A的实现需要填充一个或多个抽象B的对象
这个填充对象的过程可以结合工厂模式来增加
简单工厂/工厂方法 主要用来创建一类对象
实例化抽象A后,要给A去填充他的B属性——抽象B的具体对象
抽象工厂 主要是用来创建一系列对象的
1.实例化抽象A后,要给A去填充他的抽象B、抽象C、抽象D等一系列对象
2.创建A的系列实例化, 但这意味着B几乎无法扩展
举例:
使用工厂方法完成创建
假设分别有人类、精灵两种角色,有枪和剑两种武器,有一个条件:精灵不用枪
UML
定义角色(Character)、武器(Weapon)、武器工厂(WeaponFactory)三个抽象
namespace DesignModel.Bridge
{
//角色
public abstract class Character
{
protected Weapon primaryWeapon;
protected Weapon subWeapon;
public abstract void Attack();
public virtual void SetPrimaryWeapon(Weapon weapon)
{
primaryWeapon = weapon;
}
public virtual void SetSubWeapon(Weapon weapon)
{
subWeapon = weapon;
}
}
//武器类型
public enum WeaponType
{
Gun = 1,
Sword = 2,
}
//武器
public abstract class Weapon
{
public abstract void Attack();
public abstract WeaponType GetWeaponType();
}
//武器工厂
public interface WeaponFactory
{
Weapon CreateWeapon();
}
}
定义两种人类(Human)和精灵(Elve)
namespace DesignModel.Bridge
{
//人类
public class Human : Character
{
public override void Attack()
{
Debug.Log("Human Use : ");
//人类优先使用主武器攻击
if (primaryWeapon != null)
{
primaryWeapon.Attack();
}
else if (subWeapon != null)
{
subWeapon.Attack();
}
}
}
//精灵
public class Elve : Character
{
public override void Attack()
{
Debug.Log("Elve Use : ");
//精灵攻击逻辑
if (primaryWeapon != null)
{
primaryWeapon.Attack();
}
else if (subWeapon != null)
{
subWeapon.Attack();
}
}
public override void SetPrimaryWeapon(Weapon weapon)
{
base.SetPrimaryWeapon(weapon);
CheckGun(ref primaryWeapon);
}
public override void SetSubWeapon(Weapon weapon)
{
base.SetSubWeapon(weapon);
CheckGun(ref subWeapon);
}
//高贵的精灵从不用枪
private void CheckGun(ref Weapon weapon)
{
if (weapon.GetWeaponType() == WeaponType.Gun)
weapon = null;
}
}
}
定义武器 枪(Gun)、剑(Sword)
namespace DesignModel.Bridge
{
//枪
public class Gun : Weapon
{
public override void Attack()
{
Debug.Log("Gun Attack");
}
public override WeaponType GetWeaponType()
{
return WeaponType.Gun;
}
}
//剑
public class Sword : Weapon
{
public override void Attack()
{
Debug.Log("Sword Attack");
}
public override WeaponType GetWeaponType()
{
return WeaponType.Sword;
}
}
}
Client测试
using DesignModel.Bridge;
public class Client_Bridge_Factory : MonoBehaviour
{
void Start ()
{
//我们也可以为Character单独创建工厂,这里就简单的new了
//创建人类
Character human = new Human();
//创建精灵
Character elve = new Elve();
//创建枪A 剑A
Weapon gunA = new GunFactory().CreateWeapon();
Weapon swordA = new SwordFactory().CreateWeapon();
//给人类装备 枪A 剑A
human.SetPrimaryWeapon(gunA);
human.SetSubWeapon(swordA);
//创建 枪B 剑B
Weapon gunB = new GunFactory().CreateWeapon();
Weapon swordB = new SwordFactory().CreateWeapon();
//给精灵装备 枪B 剑B
elve.SetPrimaryWeapon(gunB);
elve.SetSubWeapon(swordB);
//人类攻击
human.Attack();
//精灵攻击
elve.Attack();
}
}
测试结果
使用抽象工厂完成创建
新增角色抽象工厂
namespace DesignModel.Bridge
{
public interface CharacterFactory
{
Character CreateGunCharacter(); //创建枪兵
Character CreateSwordCharacter(); //创建剑兵
}
}
分别实现人类工厂和精灵工厂
namespace DesignModel.Bridge
{
//人类工厂
public class HumanFactory : CharacterFactory
{
public Character CreateGunCharacter()
{
Character character = new Human();
character.SetPrimaryWeapon(new Gun());
return character;
}
public Character CreateSwordCharacter()
{
Character character = new Human();
character.SetPrimaryWeapon(new Sword());
return character;
}
}
//精灵工厂
public class ElveFactory : CharacterFactory
{
public Character CreateGunCharacter()
{
Character character = new Elve();
character.SetPrimaryWeapon(new Gun());
return character;
}
public Character CreateSwordCharacter()
{
Character character = new Elve();
character.SetPrimaryWeapon(new Sword());
return character;
}
}
}
Client测试
public class Client_Bridge_Factory : MonoBehaviour
{
void Start ()
{
Debug.Log("_________ 抽象工厂 _________");
Character humanGun = new HumanFactory().CreateGunCharacter();
humanGun.Attack();
Character elveGun = new ElveFactory().CreateGunCharacter();
elveGun.Attack();
Character elveSword = new ElveFactory().CreateSwordCharacter();
elveSword.Attack();
}
}
测试结果
观察代码可以看到,虽然抽象工厂简化了创建步骤,但是也带来了抽象工厂自身的缺点,即产品族扩展容易但种类扩展麻烦: 一维相对固定,一维容易变化
在本例中表现为武器类型扩展麻烦,完全掩盖了桥接模式本身的优点:二维抽象都可以独立变化
所以实际应用中,应当选取合适的方式去初始化