核心思想
子类沙箱模式(Subclass Sandbox)通过将核心逻辑封装在基类中,为子类提供安全的"沙箱"环境。子类通过组合或重写基类提供的预定义操作来实现行为,而非直接操作底层系统。
这种模式在游戏开发中常用于实现角色技能、AI行为等需要大量复用基础操作的系统。
模式结构
// 基类:定义沙箱方法的框架
public abstract class Superpower
{// 沙箱方法:子类必须实现的核心逻辑protected abstract void Activate();// 模板方法:控制执行流程(可选)public void Update(float deltaTime){// 前置处理(如冷却检测)if (CanActivate()){Activate();// 后置处理(如消耗资源)}}// 工具方法:提供给子类的基础操作protected void PlaySound(string soundID){AudioSystem.Instance.Play(soundID);}protected void SpawnParticles(Vector3 position, string type){ParticleSystem.Instance.Spawn(type, position);}protected Vector3 GetHeroPosition(){return HeroController.Instance.Position;}// 可选:提供默认实现的基础方法protected virtual bool CanActivate(){return true;}
}// 子类:通过组合基类方法实现具体行为
public class LightningBolt : Superpower
{protected override void Activate(){PlaySound("LIGHTNING_STRIKE");SpawnParticles(GetHeroPosition(), "ELECTRICITY");ApplyDamageToTargets();}private void ApplyDamageToTargets(){// 使用基类提供的方法实现具体逻辑}
}
关键要素
1. 沙箱方法(Activate)
- 由子类实现的抽象方法
- 使用基类提供的工具方法构建具体行为
- 示例:闪电攻击逻辑
2. 工具方法
- 基类提供的原子操作
- 封装底层系统访问(音频、粒子、输入等)
- 典型方法:
- PlaySound()
- SpawnParticles()
- GetInput()
- MoveCharacter()
3. 状态跟踪
- 通过基类维护公共状态:
-
protected float cooldownTimer; protected int remainingCharges;
4. 模板方法模式(Update)
- 控制子类方法的执行流程
- 添加公共逻辑(冷却计时、资源消耗等)
应用场景
适合场景
1.需要大量复用基础操作的系统
- 技能系统(不同技能组合相同的基础操作)
- AI行为(移动、攻击、寻路的组合)
2.需要隔离底层系统访问
- 当更换音频/粒子系统时,只需修改基类方法
3.需要统一管理公共逻辑
- 所有技能的冷却机制
- 全局的资源消耗规则
典型案例
- 技能系统
- buff/debuff效果
- 平台游戏的敌人AI行为
模式优势
1. 降低耦合
- 子类无需知道音频/粒子系统的具体实现
- 修改底层系统只需调整基类工具方法
2. 提高复用性
- 公共逻辑集中维护(如冷却计算)
- 工具方法可跨多个子类复用
3. 增强可控性
- 基类可以:
- 记录所有技能的使用统计
- 实现统一的性能优化
- 添加调试日志
4. 提升安全性
- 子类只能访问预设的操作
- 防止意外修改关键系统状态
潜在缺陷
1. 基类膨胀风险
- 当工具方法过多时,基类可能变得臃肿
- 解决方案:将工具方法按功能拆分到不同类中
2. 继承体系限制
- 不适合需要多重继承的场景
- 替代方案:组合模式 + 策略模式
3. 灵活性受限
- 子类必须遵循基类定义的模板
- 对于需要完全自由实现的场景不够灵活
进阶技巧
1. 参数化工具方法
protected void PlaySound(string id, float volume = 1f, bool loop = false)
{AudioSystem.Instance.Play(id, volume, loop);
}
2. 分层沙箱
public abstract class MagicSpell : Superpower { /* 魔法专用方法 */ }
public abstract class MeleeSkill : Superpower { /* 近战专用方法 */ }
3. 状态注入
public class Fireball : Superpower
{private float explosionRadius;public Fireball(float radius) {explosionRadius = radius;}
}
4. 配合对象池
protected GameObject GetParticleFromPool(string type)
{return ParticlePool.Instance.Get(type);
}
模式变体
1. 组件式沙箱
public class SkillSystem
{private AudioComponent audio;private ParticleComponent particles;private MovementComponent movement;public void Execute(ISkill skill){skill.Activate(audio, particles, movement);}
}
2. 基于接口的沙箱
public interface ISkillSandbox
{void PlaySound(string id);void SpawnParticles(string type);
}public class Fireball : ISkill
{public void Execute(ISkillSandbox sandbox){sandbox.PlaySound("fire_blast");}
}
总结
子类沙箱模式通过建立受控环境,在灵活性和规范性之间取得了良好平衡。
适合需要实现大量相似但存在细微差别的游戏行为场景。当发现多个子类在重复实现相同的基础操作时,可以考虑使用这个模式。
实际使用时需要注意:
- 合理划分工具方法的粒度
- 控制基类的职责范围
- 适时引入中间抽象层
- 配合其他模式(对象池、组件模式)使用
该模式的真正价值在于:当需要添加新技能或行为时,开发者可以专注于实现独特的业务逻辑,而不必担心底层系统的兼容性问题。