0.理论
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许用户通过将对象放入包含行为的特殊封装对象中来为单个对象添加新的功能,而无需修改现有的代码。这种模式创建了一个装饰器类,用来包装原有类的实例,从而在保持原类方法调用方式不变的情况下,为对象添加新的功能。
1.目的与应用场景
装饰器模式的主要目的是实现关注点的分离,增加程序的灵活性和扩展性。它允许动态地向一个对象添加额外的职责,而不改变其结构。这种模式在以下场景中特别有用:
- 当需要扩展一个类的功能,但不希望通过继承增加子类的方式,因为继承会导致类的数量急剧增加,并且降低了类的可用性。
- 当需要为一个对象添加一些特性,这些特性在不同的时间有不同的组合时。
- 在需要为一批兄弟类进行改造或添加功能时,使用装饰器模式可以避免类的爆炸。
2.实现方式
- Component(组件):定义一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(具体组件):定义了一个具体的对象,也可以给这个对象添加一些额外的职责。
- Decorator(装饰抽象类):持有一个Component对象的引用,并定义一个与Component接口一致的接口。
- ConcreteDecorator(具体装饰类):具体的装饰对象,起到给Component添加职责的功能。
在结构图 中 , ConcreteComponent 和 Decorator 需要有同样的接 口,因此ConcreteComponent 和 Decorator 有着一个共同的父类。
这里有人会问,让 Decorator 直接维护一个指向 ConcreteComponent 引用(指针)不就可以达到同样的效果,答案是肯定并且是否定的。肯定的是你可以通过这种方式实现,否定的是你不要用这种方式实现,因为通过这种方式你就只能为这个特定的 ConcreteComponent 提供修饰操作了,当有了一个新的ConcreteComponent 你 又要去新建一个Decorator 来 实 现。但是通过结构图中的ConcreteComponent 和 Decorator 有一个公共基类,就可以利用 OO (面向对象) 中多态的思想来实现只要是 Component 型别的对象都可以提供修饰操作的类,这种情况下你就算新建了 100 个Component 型别的类 ConcreteComponent也都可以由 Decorator 一个类搞定。这也正是Decorator 模式的关键和威力所在了。
1.实践
在游戏开发中,装饰器模式可以用来动态地添加或修改游戏对象的行为和属性,而无需修改原始类。这种方式非常适合于增加角色的能力、改变其外观或添加状态效果(如增益或减益状态)等场景。下面通过一个简单的例子来说明,如何在游戏中使用装饰器模式来为角色动态添加不同的能力。
假设我们有一个游戏角色类,角色可以装备各种物品来增强其属性。我们希望在不修改角色类代码的前提下,能够灵活地为角色添加不同的装备效果。
Component(组件)
首先,定义一个角色接口,所有的角色都将实现这个接口。
// 角色接口
class Character {
public:
virtual void display() = 0; // 展示角色状态
virtual ~Character() {}
};
ConcreteComponent(具体组件)
然后,实现一个具体的角色类。
// 具体的角色
class Warrior : public Character {
public:
void display() override {
std::cout << "Warrior, equipped with basic armor." << std::endl;
}
};
Decorator(装饰器抽象类)
定义一个装饰器基类,它持有一个角色接口的引用。
// 装饰器基类
class CharacterDecorator : public Character {
protected:
Character* character;
public:
CharacterDecorator(Character* character) : character(character) {}
virtual void display() override {
character->display();
}
};
ConcreteDecorator(具体装饰类)
实现具体的装饰器类,这些类通过调用Character的display方法,在执行自己的装饰功能前后,能够添加额外的行为。
// 具体装饰类:为角色添加魔法盾
class MagicShieldDecorator : public CharacterDecorator {
public:
MagicShieldDecorator(Character* character) : CharacterDecorator(character) {}
void display() override {
CharacterDecorator::display();
addMagicShield();
}
void addMagicShield() {
std::cout << "Equipped with a magical shield." << std::endl;
}
};
// 具体装饰类:为角色添加火焰剑
class FlameSwordDecorator : public CharacterDecorator {
public:
FlameSwordDecorator(Character* character) : CharacterDecorator(character) {}
void display() override {
CharacterDecorator::display();
addFlameSword();
}
void addFlameSword() {
std::cout << "Equipped with a flame sword." << std::endl;
}
};
使用示例
Character* warrior = new Warrior();
warrior->display();
// 动态地为角色添加魔法盾
Character* shieldedWarrior = new MagicShieldDecorator(warrior);
shieldedWarrior->display();
// 在已有魔法盾的基础上再添加火焰剑
Character* fullyEquippedWarrior = new FlameSwordDecorator(shieldedWarrior);
fullyEquippedWarrior->display();
输出结果
Warrior, equipped with basic armor.
Warrior, equipped with basic armor.
Equipped with a magical shield.
Warrior, equipped with basic armor.
Equipped with a magical shield.
Equipped with a flame sword.
在这个例子中,通过装饰器模式动态地为游戏角色添加了不同的装备,每个装备都增加了角色的某些属性或能力。这种方式的优点是,可以灵活地组合装备,而不需要为每种可能的装备组合创建一个新的类。这极大地减少了代码的复杂性,并增加了游戏的可扩展性。