目的
将抽象部分与实现部分分离,使它们都可以独立地变化。
适用场景
在软件系统中,某些类型由于自身的逻辑,具有两个或多个维度的变化。面对这种"多维度的变化",就可以考虑使用桥接模式。
桥接模式的核心思路是让实现和接口解耦,把继承关系改为组合关系,从而应对多个实现的变化需求。C++ 中的 Impl 手法就是桥接模式的一种典型实现方式。
一个典型场景
下面通过一个逐步演化的例子来说明桥接模式要解决的问题:
- 客户给了你一个需求,于是使用一个类来实现(A)。
- 客户需求变化,出现两个算法来实现同一功能。于是改变设计:通过一个抽象基类,再定义两个具体类来实现两种不同的算法(A1 和 A2)。
- 客户又告诉我们要适配不同的操作系统。于是再抽象一个层次,作为一个抽象基类 A0,并分别为每个操作系统派生具体类(A00 和 A01,其中 A00 表示原来的类 A),实现不同操作系统上的客户需求。这样我们就有了一共 4 个类。
- 用户的需求可能还会继续变化,比如又多了一种新的算法……
- 我们陷入了一个需求不断变化的郁闷当中,也因此带来了类数量的迅速膨胀。
Bridge 模式正是解决了这一类问题。
例子 1
class AbstractionImpl
{
public:
virtual void Operation() = 0;
};
class AbstractionImplA :public AbstractionImpl
{
public:
virtual void Operation()override
{
cout << "do Action" << endl;
}
};
class Abstraction
{
public:
virtual void Operation() = 0;
};
class RefinedAbstrantion :public Abstraction
{
public:
virtual void Operation()override
{
impl->Operation();
}
RefinedAbstrantion(AbstractionImpl *impl)
{
this->impl = impl;
}
private:
AbstractionImpl *impl;
};
int main(int argc, char *argv[])
{
AbstractionImpl *impl = new AbstractionImplA;
Abstraction *abs = new RefinedAbstrantion(impl);
abs->Operation();
system("pause");
return 0;
}
//达到了 多个变化的维度,而不是通过简单的继承
例子 2:玩家和武器系统
class Weapon
{
public:
virtual void use() = 0;
};
class WeaponImpl
{
public:
void use()
{
weapon->use();
}
WeaponImpl(Weapon* wea)
{
this->weapon = wea;
}
private:
Weapon * weapon;
};
class Gun :public Weapon
{
public:
virtual void use()override
{
cout << "shoot" << endl;
}
};
class Player
{
public:
void EquipWeapon(WeaponImpl* weapon)
{
this->weaponImpl = weapon;
}
void useWeapon()
{
weaponImpl->use();
}
private:
WeaponImpl *weaponImpl;
};
int main(int argc, char *argv[])
{
WeaponImpl* impl = new WeaponImpl(new Gun);
Player *player = new Player;
player->EquipWeapon(impl);
player->useWeapon();
return 0;
}