当前位置: 首页 > news >正文

装 饰 器 模 式

“装饰还是武器,都由我来定义。”

——柯莱塔·莫塔里

只是突然想起台词,并非魔怔!

正如同漂泊者被赠与的猫眼石一般,装饰品是独立于本体之外的事物。装饰器模式(Decorator)允许向一个现有的对象添加新的功能,同时又不改变其结构,只是作为附加物存在。


使用场景:

装饰器模式是一种结构型模式,常常用在需要运行时动态添加或修改类的功能时。就比如我们玩游戏时常遇到的“buff”。作为游戏角色的附加效果,完全可以通过装饰器模式实现。

实现:

装饰器模式包含以下四种角色:

1、抽象组件,按照设计模式大家族的传统,抽象就代表接口的意思。而这里的组件,便是我们的装饰器所要装饰的对象。

2、具体组件,组件的具体实现。

3、抽象装饰器,装饰器的基类,统一规范,而这一装饰器基类必须继承自抽象组件。

4、具体装饰器,装饰器的具体实现。

那么为什么必须用继承来连接装饰器和被装饰对象呢?

我们已经明确了装饰器在不改变修饰对象内容的前提下为其附加效果,那么这样一来装饰器必须传入两样东西:要装饰的对象要添加的效果,最终输出的是已经带有效果的对象。当我们直接使用原来的对象时,会将原本的内容直接输出,而当使用适配器时,我们为了输出带有效果的对象,我们需要一个原来对象的实例,通过组合连接,为了让得到输出的结果一致,再通过继承规范实现。所以我们的抽象器既要组合组件,也要继承于组件基类。

只靠讲的还是太啰嗦了!上代码!

那么以下是C++实现。

#include <iostream>
using namespace std;
#include <memory>
/*抽象组件*/
//游戏角色接口
class Character {
public:
virtual int getAttack() = 0; //获取攻击力
virtual int getDefense() = 0; //获取防御力
virtual ~Character() = default;
};
/*具体组件*/
class Goblin : public Character {
public:
int getAttack() override {
return 10; //哥布林的攻击力}
int getDefense() override {
return 5; //哥布林的防御力}
};
class Slime : public Character {
public:
int getAttack() override {
return 5; //史莱姆的攻击力}
int getDefense() override {
return 2; //史莱姆的防御力}
};
/*抽象装饰器*/
//继承自游戏角色接口,这样一来,规范与角色一致,使用时装饰器就可以被用来装饰任何游戏角色
class CharacterDecorator : public Character {
public:
//这个成员代码被装饰的角色,作用就是“被装饰”!Character* character;CharacterDecorator(Character* character) : character(character) {}
//基类将它们委托给被装饰的角色,默认情况下,装饰器不改变角色的行为,
int getAttack() override {
return character->getAttack();}
int getDefense() override {
return character->getDefense();}
virtual ~CharacterDecorator() {delete character;}
};
/*具体装饰器*/
class ArmorDecorator : public CharacterDecorator {
public:ArmorDecorator(Character* character) : CharacterDecorator(character) {}
int getAttack() override {
return character->getAttack();}
int getDefense() override {
return character->getDefense() + 5; //防御力buff加成5}
};
class WeaponDecorator : public CharacterDecorator {
public:WeaponDecorator(Character* character) : CharacterDecorator(character) {}
int getAttack() override {
return character->getAttack() + 5; //攻击力buff加成5}
int getDefense() override {
return character->getDefense();}
};
int main() {
//创建一个哥布林角色Character* goblin = new Goblin();cout << "哥布林攻击力: " << goblin->getAttack() << endl;cout << "哥布林防御力: " << goblin->getDefense() << endl;
//给哥布林添加护甲buff装饰器goblin = new ArmorDecorator(goblin);cout << "哥布林攻击力: " << goblin->getAttack() << endl;cout << "哥布林防御力: " << goblin->getDefense() << endl;
//给哥布林添加攻击buff装饰器goblin = new WeaponDecorator(goblin);cout << "哥布林攻击力: " << goblin->getAttack() << endl;cout << "哥布林防御力: " << goblin->getDefense() << endl;
//注意:这里内存没有释放干净,会引发内存泄露,建议使用智能执指针!
//将Character*改为std::shared_ptr<Character>,装饰器中使用std::make_shared来创建对象
//此处只作为参考delete goblin; //释放内存
return 0;
}

这样看来,装饰器继承于角色类,其输出为带buff的角色,可以直接代替原来的角色。通过这一点,我们可以做到buff叠加,也就是嵌套装饰器


小结

装饰器模式就到此为止了,在游戏开发中,不仅是角色的buff,还有环境效果、特殊增益,甚至NPC的行为逻辑,都有装饰器模式的用武之地。

如有补充交流欢迎留言,我们下次再见~

参考列表:

菜鸟教程-设计模式:www.runoob.com

http://www.dtcms.com/a/312091.html

相关文章:

  • 深入 Go 底层原理(七):逃逸分析
  • C++ 11 模板萃取
  • 丑数-优先队列/三指针/动态规划
  • Linux 动静态库的制作和使用
  • 深度剖析PyTorch torch.compile的性能曲线与优化临界点
  • SpringBoot 01 IOC
  • PyTorch 张量核心操作——比较、排序与数据校验
  • java实现运行SQL脚本完成数据迁移
  • 通俗易懂解释Java8 HashMap
  • Rust进阶-part1-智能指针概述-box指针
  • 【多模态】DPO学习笔记
  • 嵌入式文件系统
  • Java中Lambda 表达式的解释
  • PCB铜浆塞孔工艺流程
  • 如何快速解决PDF解密新方法?
  • 使用C++实现日志(1)
  • 疏老师-python训练营-Day33 MLP神经网络的训练
  • AbstractExecutorService:Java并发核心模板解析
  • 深入 Go 底层原理(一):Slice 的实现剖析
  • 二叉树链式结构的实现
  • lesson31:Python异常处理完全指南:从基础到高级实践
  • 乌鸫科技前端二面
  • Go语言中的闭包详解
  • OpenCV学习 day3
  • stm32是如何实现电源控制的?
  • 如何防止内存攻击(Buffer Overflow, ROP)
  • 髋臼方向的定义与测量-I
  • u-boot启动过程(NXP6ULL)
  • android studio 安装Flutter
  • WD5208S,12V500MA,应用于小家电电源工业控制领域