装饰模式(Decorator Pattern)是结构型设计模式中极具灵活性的一种,其核心设计思想是在不改变原有对象结构和核心逻辑的前提下,动态地为对象添加额外职责 。它摒弃了传统继承带来的强耦合与类爆炸问题,以“组合替代继承”的方式,实现功能的灵活扩展与叠加,完美契合“开闭原则”——对功能扩展开放,对原有代码修改关闭,是动态扩展对象能力的核心解决方案。
一、装饰模式的核心结构 装饰模式的设计核心是“动态附加职责”,通过四个角色的分工协作,实现核心功能与扩展功能的解耦,确保扩展逻辑可灵活组合、独立迭代,各角色职责清晰、边界明确:
抽象组件(Component) :定义对象的核心行为接口,是被装饰者(具体组件)和装饰者(抽象装饰器)的共同基类/接口,规范了所有对象的统一行为,确保装饰器与被装饰对象可无缝兼容。
具体组件(Concrete Component) :实现抽象组件的核心功能,是装饰模式的“基础对象”,也是被装饰的原始载体,专注于实现业务核心逻辑,不关注任何扩展功能。
抽象装饰器(Decorator) :继承或实现抽象组件,同时持有一个抽象组件的实例引用,作为所有具体装饰器的基类。其核心作用是搭建“装饰桥梁”,确保具体装饰器能嵌套包装被装饰对象,同时转发核心方法调用。
具体装饰器(Concrete Decorator) :继承抽象装饰器,是扩展功能的具体实现载体。它在调用被装饰对象核心方法的基础上,附加额外的扩展逻辑,完成“装饰”效果,且多个具体装饰器可嵌套组合,实现功能叠加。
核心逻辑拆解:抽象装饰器通过持有抽象组件的引用,实现对被装饰对象的“包装”;具体装饰器在不修改被装饰对象代码的前提下,动态附加新功能,且装饰器之间可灵活组合,形成链式装饰效果。例如:一杯基础咖啡(具体组件),可依次添加牛奶(具体装饰器1)、糖(具体装饰器2)、冰块(具体装饰器3),每一步装饰都不改变咖啡本身,却不断丰富其功能。
二、多语言实现装饰模式 装饰模式的核心是“动态包装与功能叠加”,不同语言因语法特性差异,实现方式略有不同,但核心逻辑高度统一。以下基于“饮品加料”的通用场景(基础饮品为核心组件,加料为装饰器),实现C#、Python、Golang、C++、纯C五种语言的完整可运行案例,清晰呈现各语言的适配方式,代码均添加规范注释,便于直接复用。
2.1 C# 实现(面向对象标准实现) C# 作为强类型面向对象语言,通过接口清晰界定抽象组件规范,抽象装饰器继承接口并组合组件实例,具体装饰器实现扩展逻辑,代码结构严谨、可维护性高,贴合企业级开发规范。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 using System;public interface IDrink { string GetDescription () ; decimal GetCost () ; } public class Coffee : IDrink { public string GetDescription () => "基础咖啡(纯黑)" ; public decimal GetCost () => 10.00 m; } public abstract class DrinkDecorator : IDrink { protected IDrink _drink; public DrinkDecorator (IDrink drink ) { _drink = drink; } public abstract string GetDescription () ; public abstract decimal GetCost () ; } public class MilkDecorator : DrinkDecorator { public MilkDecorator (IDrink drink ) : base (drink ) { } public override string GetDescription () => $"{_drink.GetDescription()} + 鲜牛奶" ; public override decimal GetCost () => _drink.GetCost() + 2.00 m; } public class SugarDecorator : DrinkDecorator { public SugarDecorator (IDrink drink ) : base (drink ) { } public override string GetDescription () => $"{_drink.GetDescription()} + 白砂糖" ; public override decimal GetCost () => _drink.GetCost() + 1.00 m; } public class IceDecorator : DrinkDecorator { public IceDecorator (IDrink drink ) : base (drink ) { } public override string GetDescription () => $"{_drink.GetDescription()} + 冰块" ; public override decimal GetCost () => _drink.GetCost(); } class Program { static void Main () { IDrink drink = new Coffee(); Console.WriteLine($"{drink.GetDescription()} :{drink.GetCost():F2} 元" ); drink = new MilkDecorator(drink); Console.WriteLine($"{drink.GetDescription()} :{drink.GetCost():F2} 元" ); drink = new SugarDecorator(drink); drink = new IceDecorator(drink); Console.WriteLine($"{drink.GetDescription()} :{drink.GetCost():F2} 元" ); } }
2.2 Python 实现(动态语言简洁实现) Python 遵循“鸭子类型”,无需显式定义接口,通过基类模拟抽象组件,抽象装饰器继承基类并组合被装饰对象,具体装饰器实现扩展逻辑,代码简洁灵活,无需繁琐的类型声明,适配快速开发与脚本场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 class Drink : def get_description (self ): """获取饮品描述,子类需实现该方法""" raise NotImplementedError("具体饮品需实现描述方法" ) def get_cost (self ): """获取饮品价格,子类需实现该方法""" raise NotImplementedError("具体饮品需实现价格方法" ) class Coffee (Drink ): def get_description (self ): return "基础咖啡(纯黑)" def get_cost (self ): return 10.0 class DrinkDecorator (Drink ): def __init__ (self, drink ): self ._drink = drink class MilkDecorator (DrinkDecorator ): def get_description (self ): return f"{self._drink.get_description()} + 鲜牛奶" def get_cost (self ): return self ._drink.get_cost() + 2.0 class SugarDecorator (DrinkDecorator ): def get_description (self ): return f"{self._drink.get_description()} + 白砂糖" def get_cost (self ): return self ._drink.get_cost() + 1.0 class IceDecorator (DrinkDecorator ): def get_description (self ): return f"{self._drink.get_description()} + 冰块" def get_cost (self ): return self ._drink.get_cost() if __name__ == "__main__" : drink = Coffee() print (f"{drink.get_description()} :{drink.get_cost():.2 f} 元" ) drink = MilkDecorator(drink) print (f"{drink.get_description()} :{drink.get_cost():.2 f} 元" ) drink = SugarDecorator(drink) drink = IceDecorator(drink) print (f"{drink.get_description()} :{drink.get_cost():.2 f} 元" )
2.3 Go 实现(组合优于继承的极简实现) Go 语言无类和继承概念,核心遵循“组合优于继承”的设计哲学,通过接口定义抽象组件规范,通过结构体组合实现装饰器与被装饰对象的关联,无需继承,代码极简、高效,贴合Go语言的设计理念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 package mainimport "fmt" type Drink interface { Description() string tCost() float64 } type Coffee struct {}func (c *Coffee) GetDescription() string { "基础咖啡(纯黑)" } func (c *Coffee) GetCost() float64 { eturn 10.0 } type DrinkDecorator struct { rink Drink } type MilkDecorator struct { DrinkDecorator } func NewMilkDecorator (drink Drink) *MilkDecorator { return &MilkDecorator{DrinkDecorator{drink: drink}} } func (m *MilkDecorator) GetDescription() string { eturn fmt.Sprintf("%s + 鲜牛奶" , m.drink.GetDescription()) } func (m *MilkDecorator) GetCost() float64 { turn m.drink.GetCost() + 2.0 } type SugarDecorator struct { nkDecorator } func NewSugarDecorator (drink Drink) *SugarDecorator { return &SugarDecorator{DrinkDecorator{drink: drink}} } func (s *SugarDecorator) GetDescription() string { rn fmt.Sprintf("%s + 白砂糖" , s.drink.GetDescription()) } func (s *SugarDecorator) GetCost() float64 { turn s.drink.GetCost() + 1.0 } type IceDecorator struct { rinkDecorator } func NewIceDecorator (drink Drink) *IceDecorator { &IceDecorator{DrinkDecorator{drink: drink}} } func (i *IceDecorator) GetDescription() string { turn fmt.Sprintf("%s + 冰块" , i.drink.GetDescription()) } func (i *IceDecorator) GetCost() float64 { eturn i.drink.GetCost() } func main () { r drink Drink = &Coffee{} t.Printf("%s:%.2f元\n" , drink.GetDescription(), drink.GetCost()) / 咖啡 + 牛奶 rink = NewMilkDecorator(drink) .Printf("%s:%.2f元\n" , drink.GetDescription(), drink.GetCost()) 牛奶 + 糖 + 冰块 nk = NewSugarDecorator(drink) rink = NewIceDecorator(drink) fmt.Printf("%s:%.2f元\n" , drink.GetDescription(), drink.GetCost()) } d dri
2.4 C++ 实现(面向对象经典实现) C++ 作为经典面向对象语言,通过抽象类(纯虚函数)定义抽象组件和抽象装饰器,具体装饰器继承抽象装饰器并持有组件指针,依托多态实现动态装饰,兼顾灵活性与性能,适配底层开发与高性能场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 #include <iostream> #include <string> #include <iomanip> class Drink {public : virtual ~Drink () = default ; virtual std::string getDescription () = 0 ; virtual double getCost () = 0 ; }; class Coffee : public Drink {public : std::string getDescription () override { return "基础咖啡(纯黑)" ; } double getCost () override { return 10.0 ; } }; class DrinkDecorator : public Drink {protected : Drink* _drink; public : DrinkDecorator (Drink* drink) : _drink(drink) {} virtual ~DrinkDecorator () { delete _drink; } }; class MilkDecorator : public DrinkDecorator {public : MilkDecorator (Drink* drink) : DrinkDecorator (drink) {} std::string getDescription () override { return _drink->getDescription () + " + 鲜牛奶" ; } double getCost () override { return _drink->getCost () + 2.0 ; } }; class SugarDecorator : public DrinkDecorator {public : SugarDecorator (Drink* drink) : DrinkDecorator (drink) {} std::string getDescription () override { return _drink->getDescription () + " + 白砂糖" ; } double getCost () override { return _drink->getCost () + 1.0 ; } }; class IceDecorator : public DrinkDecorator {public : IceDecorator (Drink* drink) : DrinkDecorator (drink) {} std::string getDescription () override { return _drink->getDescription () + " + 冰块" ; } double getCost () override { return _drink->getCost (); } }; int main () { Drink* drink = new Coffee (); std::cout << drink->getDescription () << ":" << std::fixed << std::setprecision (2 ) << drink->getCost () << "元" << std::endl; drink = new MilkDecorator (drink); std::cout << drink->getDescription () << ":" << std::fixed << std::setprecision (2 ) << drink->getCost () << "元" << std::endl; drink = new SugarDecorator (drink); drink = new IceDecorator (drink); std::cout << drink->getDescription () << ":" << std::fixed << std::setprecision (2 ) << drink->getCost () << "元" << std::endl; delete drink; return 0 ; }
2.5 纯C语言实现(结构体+函数指针模拟实现) 纯C语言无面向对象特性,通过“结构体封装数据+函数指针模拟方法”,模拟抽象组件、具体组件和装饰器的核心逻辑,依托结构体嵌套和函数指针赋值,实现动态装饰与功能叠加,代码虽冗余但底层可控,适配嵌入式、底层开发场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> typedef char * (*GetDescriptionFunc)(void *);typedef double (*GetCostFunc) (void *) ;typedef struct { GetDescriptionFunc get_description; GetCostFunc get_cost; } Drink; typedef struct { Drink drink; } Coffee; char * Coffee_GetDescription (void * self) { return "基础咖啡(纯黑)" ; } double Coffee_GetCost (void * self) { return 10.0 ; } Coffee* Coffee_Create () { Coffee* coffee = (Coffee*)malloc (sizeof (Coffee)); if (coffee == NULL ) return NULL ; coffee->drink.get_description = Coffee_GetDescription; coffee->drink.get_cost = Coffee_GetCost; return coffee; } typedef struct { Drink drink; Drink* wrapped_drink; } DrinkDecorator; typedef struct { DrinkDecorator decorator; } MilkDecorator; char * Milk_GetDescription (void * self) { MilkDecorator* decorator = (MilkDecorator*)self; char * base_desc = decorator->decorator.wrapped_drink->get_description(decorator->decorator.wrapped_drink); char * new_desc = (char *)malloc (strlen (base_desc) + strlen (" + 鲜牛奶" ) + 1 ); strcpy (new_desc, base_desc); strcat (new_desc, " + 鲜牛奶" ); return new_desc; } double Milk_GetCost (void * self) { MilkDecorator* decorator = (MilkDecorator*)self; return decorator->decorator.wrapped_drink->get_cost(decorator->decorator.wrapped_drink) + 2.0 ; } MilkDecorator* MilkDecorator_Create (Drink* drink) { MilkDecorator* decorator = (MilkDecorator*)malloc (sizeof (MilkDecorator)); if (decorator == NULL ) return NULL ; decorator->decorator.drink.get_description = Milk_GetDescription; decorator->decorator.drink.get_cost = Milk_GetCost; decorator->decorator.wrapped_drink = drink; return decorator; } typedef struct { DrinkDecorator decorator; } SugarDecorator; char * Sugar_GetDescription (void * self) { SugarDecorator* decorator = (SugarDecorator*)self; char * base_desc = decorator->decorator.wrapped_drink->get_description(decorator->decorator.wrapped_drink); char * new_desc = (char *)malloc (strlen (base_desc) + strlen (" + 白砂糖" ) + 1 ); strcpy (new_desc, base_desc); strcat (new_desc, " + 白砂糖" ); return new_desc; } double Sugar_GetCost (void * self) { SugarDecorator* decorator = (SugarDecorator*)self; return decorator->decorator.wrapped_drink->get_cost(decorator->decorator.wrapped_drink) + 1.0 ; } SugarDecorator* SugarDecorator_Create (Drink* drink) { SugarDecorator* decorator = (SugarDecorator*)malloc (sizeof (SugarDecorator)); if (decorator == NULL ) return NULL ; decorator->decorator.drink.get_description = Sugar_GetDescription; decorator->decorator.drink.get_cost = Sugar_GetCost; decorator->decorator.wrapped_drink = drink; return decorator; } typedef struct { DrinkDecorator decorator; } IceDecorator; char * Ice_GetDescription (void * self) { IceDecorator* decorator = (IceDecorator*)self; char * base_desc = decorator->decorator.wrapped_drink->get_description(decorator->decorator.wrapped_drink); char * new_desc = (char *)malloc (strlen (base_desc) + strlen (" + 冰块" ) + 1 ); strcpy (new_desc, base_desc); strcat (new_desc, " + 冰块" ); return new_desc; } double Ice_GetCost (void * self) { IceDecorator* decorator = (IceDecorator*)self; return decorator->decorator.wrapped_drink->get_cost(decorator->decorator.wrapped_drink); } IceDecorator* IceDecorator_Create (Drink* drink) { IceDecorator* decorator = (IceDecorator*)malloc (sizeof (IceDecorator)); if (decorator == NULL ) return NULL ; decorator->decorator.drink.get_description = Ice_GetDescription; decorator->decorator.drink.get_cost = Ice_GetCost; decorator->decorator.wrapped_drink = drink; return decorator; } int main () { Coffee* coffee = Coffee_Create(); Drink* drink = (Drink*)coffee; printf ("%s:%.2f元\n" , drink->get_description(coffee), drink->get_cost(coffee)); MilkDecorator* milk = MilkDecorator_Create(drink); drink = (Drink*)milk; char * desc1 = drink->get_description(milk); printf ("%s:%.2f元\n" , desc1, drink->get_cost(milk)); free (desc1); SugarDecorator* sugar = SugarDecorator_Create(drink); drink = (Drink*)sugar; IceDecorator* ice = IceDecorator_Create(drink); drink = (Drink*)ice; char * desc2 = drink->get_description(ice); printf ("%s:%.2f元\n" , desc2, drink->get_cost(ice)); free (desc2); free (ice); free (sugar); free (milk); free (coffee); return 0 ; }
三、装饰模式的优缺点 装饰模式的核心价值是“动态扩展、解耦职责”,其优缺点均围绕这一核心展开,需结合系统复杂度和扩展需求权衡使用,避免过度设计或滥用。
3.1 核心优点
灵活性远超继承 :无需创建大量子类(避免类爆炸问题),可在运行时动态为对象添加/移除职责,灵活组合多个装饰器,实现功能的叠加扩展,比继承更具弹性。
完全符合开闭原则 :扩展新功能只需新增具体装饰器类/结构体,无需修改原有核心代码(抽象组件、具体组件),降低系统修改风险,提升可维护性。
职责清晰解耦 :核心功能与扩展功能分离,具体组件专注于实现业务核心逻辑,装饰器专注于实现扩展逻辑,代码职责单一,便于维护和迭代。
支持多层嵌套装饰 :多个装饰器可嵌套组合,实现复杂功能的叠加(如咖啡+牛奶+糖+冰块),且装饰器之间相互独立,可自由组合。
不改变原有对象结构 :装饰器仅通过“包装”方式附加功能,不修改原有对象的代码和结构,避免破坏原有逻辑的稳定性。
3.2 主要缺点
增加系统复杂度 :过多的装饰器会导致系统中类/结构体数量增加,同时多层嵌套装饰会形成调用链,增加代码的理解成本和调试难度。
装饰器顺序敏感 :部分场景下,装饰器的执行顺序会影响最终结果(如“权限校验装饰器”需在“日志记录装饰器”之前执行),顺序错误会导致业务逻辑异常。
调试难度提升 :多层装饰嵌套后,定位问题需逐层追溯装饰器的调用流程,无法直接定位到问题源头,增加调试成本。
纯C等语言实现繁琐 :无面向对象特性的语言,需通过结构体+函数指针模拟装饰逻辑,代码冗余度高,维护不便。
四、装饰模式的使用场景 装饰模式的核心适用场景是“需动态扩展对象功能、避免继承爆炸、核心功能与扩展功能解耦”,具体场景如下,同时补充典型实战案例,便于理解落地:
动态扩展对象功能 :需在运行时为对象添加/移除职责,且扩展功能不固定(如电商系统中,订单的折扣、满减、优惠券等优惠规则,可通过装饰器动态组合,不同订单适用不同优惠组合)。
避免继承导致的类爆炸 :当一个对象的扩展方向较多(如UI组件的边框、阴影、高亮、禁用等样式),若用继承需为每种样式组合创建子类,装饰模式可通过组合装饰器实现,大幅减少类数量。
功能可叠加/撤销 :需实现功能的多层叠加,或支持动态撤销扩展功能(如IO流操作:文件流+缓冲流+加密流,可自由组合或移除某一层流;日志框架的多处理器:控制台日志+文件日志+远程上报日志,可动态添加或移除日志输出方式)。
核心功能稳定,扩展功能多变 :基础核心逻辑稳定,扩展功能频繁迭代(如支付系统的基础支付功能不变,扩展微信支付、支付宝、银联等支付渠道时,用装饰器封装各渠道的差异化逻辑,不影响核心支付流程)。
不允许修改原有对象代码 :第三方组件、遗留系统的对象,无法修改其源码,需通过装饰器附加新功能,实现兼容扩展。
典型实战案例
IO流框架:如Java的InputStream/OutputStream、C#的FileStream,通过装饰器模式实现缓冲、加密、压缩等功能的叠加(如BufferedInputStream装饰FileInputStream,实现缓冲读取)。
日志框架:如Log4j、NLog,通过装饰器动态添加日志过滤、格式化、多输出源(控制台、文件、数据库)等功能,灵活配置日志输出规则。
UI组件库:如前端的按钮、输入框,通过装饰器添加边框、阴影、hover效果、禁用状态等样式,避免为每种样式组合创建独立组件。
权限校验系统:接口请求的权限校验、参数校验、日志记录,通过装饰器嵌套实现(如先校验权限,再校验参数,最后记录日志),职责分离且可灵活组合。
电商优惠系统:订单结算时,折扣、满减、优惠券、积分抵扣等优惠规则,通过装饰器动态组合,不同订单匹配不同优惠组合,扩展性极强。
五、总结 装饰模式的核心是“动态包装、职责解耦”,其本质是通过“组合替代继承”,解决了继承带来的灵活性不足、类爆炸等痛点,实现对象功能的动态扩展与叠加。它的核心价值不在于“简化代码”,而在于“优化扩展能力”,让系统在不修改原有代码的前提下,快速迭代新功能,同时保持核心逻辑的稳定性。
从多语言实现来看,尽管语法形式差异显著,但核心逻辑高度统一,且适配不同语言的设计理念:
面向对象语言(C#、Python、C++):依托接口/抽象类定义核心规范,通过继承扩展装饰器,通过组合建立装饰关联,代码结构清晰、易维护,适配大多数企业级开发场景;
Go语言:遵循“组合优于继承”,通过接口定义组件规范,通过结构体嵌套组合装饰器与被装饰对象,极简高效,贴合语言的设计哲学;
纯C语言:通过结构体+函数指针模拟面向对象特性,手动实现装饰逻辑,底层可控,适配嵌入式、底层开发等资源受限场景。
在工程实践中,使用装饰模式需注意三点:一是控制装饰器的数量,避免过度嵌套导致的复杂度提升;二是明确装饰器的执行顺序,避免因顺序错误引发业务异常;三是避免滥用,简单场景(无动态扩展需求)下,直接添加方法或使用继承更简洁。当系统需要动态扩展功能、核心与扩展逻辑解耦、避免类爆炸时,装饰模式是最优设计方案之一,是每一位开发者必备的架构设计工具。