• 设计模式:装饰模式


    先说一个反例:

    我们有三个流类,继承自流基类:

    1. class Stream {
    2. protected:
    3. virtual void Read() = 0;
    4. virtual void Seek() = 0;
    5. virtual void Write() = 0;
    6. };
    7. class Stream1:public Stream {
    8. void Read() {
    9. //Stream1的读取方法
    10. }
    11. void Seek() {
    12. //Stream1的定位方法
    13. }
    14. void Write() {
    15. //Stream1的写方法
    16. }
    17. };
    18. class Stream2 :public Stream {
    19. void Read() {
    20. //Stream2的读取方法
    21. }
    22. void Seek() {
    23. //Stream2的定位方法
    24. }
    25. void Write() {
    26. //Stream2的写方法
    27. }
    28. };
    29. class Stream3 :public Stream {
    30. void Read() {
    31. //Stream3的读取方法
    32. }
    33. void Seek() {
    34. //Stream3的定位方法
    35. }
    36. void Write() {
    37. //Stream3的写方法
    38. }
    39. };

    然后我们要对这3个类的留进行加密,我们可以用继承来写:

    1. class Stream {
    2. protected:
    3. virtual void Read() = 0;
    4. virtual void Seek() = 0;
    5. virtual void Write() = 0;
    6. };
    7. class Stream1:public Stream {
    8. public:
    9. virtual void Read() {
    10. //Stream1的读取方法
    11. }
    12. virtual void Seek() {
    13. //Stream1的定位方法
    14. }
    15. virtual void Write() {
    16. //Stream1的写方法
    17. }
    18. };
    19. class Stream2 :public Stream {
    20. public:
    21. virtual void Read() {
    22. //Stream2的读取方法
    23. }
    24. virtual void Seek() {
    25. //Stream2的定位方法
    26. }
    27. virtual void Write() {
    28. //Stream2的写方法
    29. }
    30. };
    31. class Stream3 :public Stream {
    32. public:
    33. virtual void Read() {
    34. //Stream3的读取方法
    35. }
    36. virtual void Seek() {
    37. //Stream3的定位方法
    38. }
    39. virtual void Write() {
    40. //Stream3的写方法
    41. }
    42. };
    43. class CryptoStream1 :public Stream1 {
    44. public:
    45. virtual void Write() {
    46. //加密
    47. //写方法
    48. }
    49. };
    50. class CryptoStream2 :public Stream2 {
    51. public:
    52. virtual void Write() {
    53. //加密
    54. //写方法
    55. }
    56. };
    57. class CryptoStream3 :public Stream3 {
    58. public:
    59. virtual void Write() {
    60. //加密
    61. //写方法
    62. }
    63. };

    这里就有问题了,其中加密方法我们是不变的,用的是同一种加密算法,但是我们得写3遍,嗯....

    bad smell;

    我们可以采用装饰模式来解决这个问题

    UML如下

     其中Component是抽象接口,ConcreteComponent是具体的对象,Decorator是装饰器与Component之间的中间类,一般里面会有一个Component的指针,用来访问ConcreteComponent

    Decorator与Component的关系很特殊,即是继承关系又是组合关系,继承关系是为了获取接口,组合关系是为了访问子类;

    以下是个人的理解:

    1:如果我们用继承来解决加密的需求,那么会给扩展出来的类加上编译时的静态特征,既然是静态,那么对于变化,就是不堪一击的,只要需求一遍,只能在修改静态特征,如果有其他类依赖这个类,那么很显然,牵一发动全身。

    2:如果我们用装饰模式来解决加密的需求,那么我们可以获得动态的特征,我们可以随着需求的改变,动态地调整装饰器中的指针指向的子类,充分地利用了多态性,在开始的例子里面,我们添加新的流类,如果这个流类依然用的是让一个加密算法,那么Decorate不用变,如果我们增加新的加密算法,我们只需要继承Decorate写一个新的修饰类,而不用为每个流类设计一个新的加密类。

    3:继承方式打破了设计模式八股文之:依赖倒置原则,即高层模块不依赖于低层模块。

    其中加密类可以视为高层模块,其中流类是低沉模块,因为高层模块依赖了底层模块,所以限制了高层模块的扩展性。

    也打破了八股文之优先使用对象组合,而不是类继承

  • 相关阅读:
    设计模式之单例模式
    《实用软件工程》课程教学大纲(Practicality Software Engineering)
    AirServer投屏轻松地将iPhone、iPad投屏到Mac上面教程
    web安全渗透
    Vite+Vue3+Pinia+pnpm项目开发快速入门
    BE节点经常挂掉:[IO_ERROR]failed to list /proc/27349/fd/: No such file or directory
    java标注
    Unity之"诡异"的协程
    单实例单实例Oracle数据库,RMAN,故障的应对
    Linux基本指令(上)
  • 原文地址:https://blog.csdn.net/weixin_62953519/article/details/126344132