分享

一文搞懂怎么用C语言实现装饰模式

 新用户0118F7lQ 2023-07-09 发布于山东

1, 介绍

    装饰模式是一种结构型设计模式,它能在程序运行时,动态地为对象添加新功能,而不改变其结构。在不改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。装饰模式最终的目的就是“装饰”对象,其中装饰抽象类扮演着至关重要的角色,它实现了组件的通用接口,并且使自身抽象化以迫使子类继承,使装饰固定特性的延续与多态化成为可能。

    像其他设计模式一样,装饰模式也抽象、封装了软件中存在变化的部分。装饰模式合理地使用类继承和组合的方式,非常灵活地表达了对象之间的依赖关系。装饰模式使用抽象对组件的扩展功能进行封装,装饰者和被装饰者完全隔离开来,这样我们就可以任意地改变装饰者和被装饰者,而不会引起影响。

    装饰模式很好的利用了开闭原则,在需要对组件进行扩展。增加新功能时,只要实现一个特性的装饰者,对原有的软件功能结构没有印象概念股,对用户程序也是透明的。

    在装饰模式中,装饰者的角色就是抽象类实现,面向抽象编程的好处就是起到了很好的接口隔离作用。

    由于类继承是强关联关系,对象组合则是弱关联关系。装饰模式合理地使用了对象组合方式,通过组合灵活扩展组件的功能,所有的扩展功能都是通过组合而非继承获得,这从根本上决定了这种实现是高内聚、低耦合的。

    装饰模式的UML类图:

图片

装饰模式的UML类图
  • Component(被装饰者抽象):是一个接口或者抽象类,就是定义最原始、基本、核心的类(对象),这个类就是我们需要装饰类的基类。用来规范准备接收附加责任或功能的对象。

  • ConcreteComponent(被装饰者具体实现):这是Component类的一个实现类,我们要装饰的就是这个具体实现类。也就是被装饰者,定义一个将要被装饰增加功能的类。

  • Decorator(装饰者):一般是一个抽象类,实现接口或者抽象方法,它里面必然有一个指向Component的变量引用。持有一个Component对象的实例,并定义了抽象Component定义的接口。

  • ConcreteDecorator(装饰者实现):具体的装饰者类,负责给被装饰者添加增加的功能,用来装饰被装饰者。

    使用装饰模式的时候需要注意几点:
  • 装饰对象和真实的对象(被装饰对象)有相同的接口。这样用户程序就可以使用与真实对象相同的方式操作装饰对象。

  • 装饰对象包含一个真实对象(被装饰对象)的引用。

  • 装饰对象接受所有来自用户的请求,并将这些请求发给真实的对象。

  • 装饰对象可以在转发这些请求时,增加一些附加功能。这样就可以确保在运行时,不用修改给定对象的结构就可以在外部增加附加功能。

    装饰模式使用对象组合的方式,灵活有效地扩展对象功能,降低了软件功能之间的耦合,做到了对扩展开放,对修改关闭。装饰模式以对用户透明的方式动态地给一个对象增加更多的功能或职责。可以在不创建更多子类的情况下,将对象的功能加以扩展,装饰模式使用原来被装饰的类的一个子类实例,把用户的调用委派到被装饰类。

2, 举例

#include <stdio.h>#include <stdlib.h>
// 被装饰者抽象接口Componenttypedef struct Component { void (*operation)(struct Component *);} Component;
// 被装饰者具体实现ConcreteComponenttypedef struct ConcreteComponent { Component base;} ConcreteComponent;
// 具体的被装饰者实现的操作void concrete_operation(Component *self) { printf('Concrete operation\n');}
// 装饰者基类typedef struct Decorator { Component base; Component *decorated;} Decorator;
// 装饰者的操作实现void decorator_operation(Component *self) { Decorator *decorator = (Decorator *)self; decorator->decorated->operation(decorator->decorated);}
// 具体的装饰者A实现typedef struct ConcreteDecoratorA { Decorator base;} ConcreteDecoratorA;
// 装饰者A装饰的功能实现void decorator_a_operation(Component *self){ printf('Excuting decoratorA operation.\n');
//调用父类方法 decorator_operation(self);}
// 具体的装饰者B实现typedef struct ConcreteDecoratorB { Decorator base;} ConcreteDecoratorB;
// 装饰者B装饰的功能实现void decorator_b_operation(Component *self){ printf('Excuting decoratorB operation.\n');
//调用父类方法 decorator_operation(self);}
int main() { // 创建被装饰者 ConcreteComponent component = { {concrete_operation} };
// 创建具体的装饰者A ConcreteDecoratorA a = { { { decorator_a_operation }, (Component *)&component } };
// 创建具体的装饰者B ConcreteDecoratorB b = { { { decorator_b_operation }, (Component *)&component } };
// 调用装饰者A的功能 Component *componenta = (Component *)&a; componenta->operation(componenta);
// 调用装饰者B的功能 Component *componentb = (Component *)&b; componentb->operation(componentb);
return 0;}

    如上程序,实现了一个被装饰者抽象接口类Component,一个被装饰者抽象接口类的具体实现类ConcreteComponent,一个装饰者基类Decorator,两个装饰者基建类的继承类(装饰者类)ConcreteDecoratorA和ConcreteDecoratorB。其中,ConcreteDecoratorA和ConcreteDecoratorB继承了基本装饰者类Decorator,可以动态地将一个装饰者类附加到被装饰者上。这样在装饰器调用被装饰者功能前会先执行新增的功能。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多