定义
基类定义抽象的沙箱方法和几个提供的操作。 将操作标为protected,表明它们只为子类所使用。 每个推导出的沙箱子类用提供的操作实现了沙箱函数。
举个例子
假设我们在做一个超级英雄的游戏,我们现在要实现一些超能力。我们计划创建一个Superpower基类。然后由它派生出各种超级能力的实现类。 由于超能力种类繁多,而且逻辑各异,有些超能力要进行大量的物理计算,有些超能力需要大量掉哟个到游戏的动画系统,有些超能力需要播放很多音频…
这意味着这些超能力需要与游戏引擎内的方法产生大量的交互调用。而且如果有些引擎的API发生了改变,可能会有大量的超能力类要重写。这样可不好,耦合性太高了,我们讨厌如此多的大量耦合。
这个时候我们就可以使用子类沙箱的方法来避免这一情况。我们要做的就是统一将所有的方法都放在基类的protected字段下,而子类都通过访问基类中的这些方法来实现自己的功能。这样就可以将众多的子类和引擎代码解耦。
代码如下:
class Superpower
{
public:
virtual ~Superpower() {}
protected:
virtual void activate() = 0;
void move(double x, double y, double z)
{
// 实现代码……
}
void playSound(SoundId sound, double volume)
{
// 实现代码……
}
void spawnParticles(ParticleType type, int count)
{
// 实现代码……
}
};
然后实现某一个子类
class SkyLaunch : public Superpower
{
protected:
virtual void activate()
{
// 空中滑行
playSound(SOUND_SPROING, 1.0f);
spawnParticles(PARTICLE_DUST, 10);
move(0, 0, 20);
}
};
我们通过将耦合约束到一个地方解决了耦合问题。 Superpower最终与不同的系统耦合,但是继承它的几百个类不会。 相反,它们只耦合基类。 当游戏系统的某部分改变时,修改Superpower也许是必须的,但是众多的子类不需要修改。这就是子类沙箱模式。
何时使用子类沙箱?
• 你有一个能推导很多子类的基类。
• 基类可以提供子类需要的所有操作。
• 在子类中有行为重复,你想要更容易地在它们间分享代码。
• 你想要最小化子类和程序的其他部分的耦合。