在Unity开发中, 装饰器模式 (Decorator Pattern) 用于动态地给对象添加额外功能, 同时不改变其原始结构. 它比继承更灵活 ——— 可以通过”包装”的上市组合多个功能, 而非通过复杂的继承链堆叠功能, 避免”类爆炸”问题.
举个具体场景: 角色攻击强化系统
假设你的游戏中有一个基础战士角色, 他的基础攻击是”物理伤害”. 随着游戏推进, 角色可能获得各种强化效果:
- 火焰附魔(攻击附加火焰伤害)
- 暴击效果(有概率造成双倍伤害)
- 吸血效果(攻击时恢复生命值)
如果用继承实现(如
WarriorWithfire \ WarriorWithFireAndCrit …), 每增加一种效果组合就要新增一个类, 扩展性极差. 装饰器模式可以解决这个问题: 用”装饰器”包裹基础角色, 动态叠加效果.装饰器模式的核心角色
- 抽象组件(Component): 定义对象的核心行为接口(如:”攻击”)
- 具体组件(ConcreteComponent): 实现抽象组件的基础对象(如”基础战士”)
- 抽象装饰器(Decorator): 实现抽象组件, 同时持有一个抽象组件的引用(用于”包装”其他组件).
- 具体装饰器(ConcreteDecorator): 继承抽象装饰器, 添加具体额外功能(如”火焰伤害””暴击”).
代码实现步骤
- 定义抽象组件(核心行为接口)
先定义角色攻击的核心接口, 规定所有”可攻击对象”必须实现
Attack() 方法:- 实现具体组件(基础角色)
这是被装饰的”基础对象”, 实现最原始的攻击逻辑:
3.实现抽象装饰器(包装基础)
抽象装饰器需要”包装”其他
IAttackable 对象(可以是基础角色, 也可以是其他装饰器), 并实现 IAttackable 接口:- 实现具体装饰器(添加额外功能)
每个具体装饰器负责添加一种额外效果, 在调用被装饰对象的
Attack() 之前/之后执行自己的逻辑:- 客户端使用(动态组合效果)
在游戏逻辑中, 通过 “嵌套包装” 的方式给角色动态添加效果, 组合顺序不影响最终功能:
装饰器模式的核心优势
- 动态组合功能: 可以在运行时给对象添加/移除功能(比如战斗中临时获得的buff), 无需修改原始对象代码.
- 避免类爆炸: 如果用继承实现 “火焰 + 暴击 + 吸血”, 需要
WarriorWithFire\WarriorWithFireAndCrit等多个类; 用装饰器只需 3个装饰器, 且可任意组合(如”暴击 + 吸血” “火焰 + 吸血”等).
- 单一职责: 每个装饰器只负责一种额外功能(火焰\暴击\吸血), 修改一个功能也不会影响其他功能.
在Unity中其他应用场景
- 道具系统: 角色使用”速度药水””力量药水”等, 每种药水通过装饰器动态添加属性加成, 效果可叠加或过期移除.
- 武器附魔: 一把剑可以同时附魔 “冰””雷””毒”, 每种附魔是一个装饰器, 攻击时依次触发效果.
- UI特效: 给按钮添加”点击音效””缩放动画””粒子特效”, 每个特效用装饰器包装, 可灵活组合.
装饰器模式 vs 继承
- 继承: 静态地在编译时确定功能, 新增组合需要新增子类, 灵活性差.
- 装饰器: 动态地在运行时组合功能, 通过包装实现, 无需新增子类, 扩展性强.
装饰器模式就像”叠buff” ——— 基础角色是”白板”, 每个buff是一个装饰器, 叠多少层\叠什么buff, 完全由你动态决定.