不落辰

知不可乎骤得,托遗响于悲风

0%

单一职责模式

单一职责模式:装饰模式、桥模式

单一职责模式

  • 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。

    装饰模式

    把编译时的事情延迟到运行时去做
    设计模式真谛:编译时让他复用;需求,变化都放到运行时。

动机

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质(写死的语句),使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?

定义

  • 动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)

结构

总结

  • 通过采用组合而非继承的手法, Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
  • Decorator类在接口上表现为is-a Component的继承关系,即 Decorator类继承了Component类所具有的接口。但在实现上又 表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。
  • Decorator模式的目的并非解决“多子类衍生的多继承”问题, Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义

  • 装饰者的继承:为了完善接口规范
    • class Deractor : public Base{}
  • 装饰者的组合:为了实现支持将来实现类的调用
    • {Base * b}
  • 看到一个class A 他既继承自父类Base,又有父类Base*成员,那么,基本上就是装饰者模式了。
  • 同时继承和组合,基本上就是装饰者模式。

重构

  • 最开始 总共有 1 + n + n*m! 个类
  • 有最普通的读,有加密的读,有缓存的读,有缓存+加密的读
    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
    //业务操作
    class Stream{
    public
    virtual char Read(int number)=0;
    virtual void Seek(int position)=0;
    virtual void Write(char data)=0;
    virtual ~Stream(){}
    };

    //主体类
    class FileStream: public Stream{
    public:
    virtual char Read(int number){
    //读文件流
    }
    virtual void Seek(int position){
    //定位文件流
    }
    virtual void Write(char data){
    //写文件流
    }
    };

    class NetworkStream :public Stream{
    public:
    virtual char Read(int number){
    //读网络流
    }
    virtual void Seek(int position){
    //定位网络流
    }
    virtual void Write(char data){
    //写网络流
    }
    };

    class MemoryStream :public Stream{
    public:
    virtual char Read(int number){
    //读内存流
    }
    virtual void Seek(int position){
    //定位内存流
    }
    virtual void Write(char data){
    //写内存流
    }
    };

    // 重复代码
    // 加密操作是一样的
    // 缓冲操作是一样的
    // read seek write操作不同类不同,但是都继承自Stream

    //扩展操作
    class CryptoFileStream :public FileStream{
    public:
    virtual char Read(int number){
    //额外的加密操作...
    FileStream::Read(number);//读文件流 // 继承引入的静态机制!
    }
    virtual void Seek(int position){
    //额外的加密操作...
    FileStream::Seek(position);//定位文件流
    //额外的加密操作...
    }
    virtual void Write(byte data){
    //额外的加密操作...
    FileStream::Write(data);//写文件流
    //额外的加密操作...
    }
    };

    class CryptoNetworkStream : :public NetworkStream{
    public:
    virtual char Read(int number){
    //额外的加密操作...
    NetworkStream::Read(number);//读网络流
    }
    virtual void Seek(int position){
    //额外的加密操作...
    NetworkStream::Seek(position);//定位网络流
    //额外的加密操作...
    }
    virtual void Write(byte data){
    //额外的加密操作...
    NetworkStream::Write(data);//写网络流
    //额外的加密操作...
    }
    };

    class CryptoMemoryStream : public MemoryStream{
    public:
    virtual char Read(int number){
    //额外的加密操作...
    MemoryStream::Read(number);//读内存流
    }
    virtual void Seek(int position){
    //额外的加密操作...
    MemoryStream::Seek(position);//定位内存流
    //额外的加密操作...
    }
    virtual void Write(byte data){
    //额外的加密操作...
    MemoryStream::Write(data);//写内存流
    //额外的加密操作...
    }
    };

    class BufferedFileStream : public FileStream{
    //...
    };

    class BufferedNetworkStream : public NetworkStream{
    //...
    };

    class BufferedMemoryStream : public MemoryStream{
    //...
    }

    class CryptoBufferedFileStream :public FileStream{
    public:
    virtual char Read(int number){
    //额外的加密操作...
    //额外的缓冲操作...
    FileStream::Read(number);//读文件流
    }
    virtual void Seek(int position){
    //额外的加密操作...
    //额外的缓冲操作...
    FileStream::Seek(position);//定位文件流
    //额外的加密操作...
    //额外的缓冲操作...
    }
    virtual void Write(byte data){
    //额外的加密操作...
    //额外的缓冲操作...
    FileStream::Write(data);//写文件流
    //额外的加密操作...
    //额外的缓冲操作...
    }
    };



    void Process(){
    //编译时装配
    CryptoFileStream *fs1 = new CryptoFileStream();
    BufferedFileStream *fs2 = new BufferedFileStream();
    CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();
    }

优化

  • 一个类 继承自Stream 且与Stream类组合
  • class CryptoStream :public Stream { Stream* stream ...}
  • 继承原因:为了实现基类的接口规范
  • 组合原因:为了实现功能
    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
    //业务操作
    class Stream{

    public
    virtual char Read(int number)=0;
    virtual void Seek(int position)=0;
    virtual void Write(char data)=0;

    virtual ~Stream(){}
    };

    //主体类
    class FileStream: public Stream{
    public:
    virtual char Read(int number){
    //读文件流
    }
    virtual void Seek(int position){
    //定位文件流
    }
    virtual void Write(char data){
    //写文件流
    }

    };

    class NetworkStream :public Stream{
    public:
    virtual char Read(int number){
    //读网络流
    }
    virtual void Seek(int position){
    //定位网络流
    }
    virtual void Write(char data){
    //写网络流
    }

    };

    class MemoryStream :public Stream{
    public:
    virtual char Read(int number){
    //读内存流
    }
    virtual void Seek(int position){
    //定位内存流
    }
    virtual void Write(char data){
    //写内存流
    }

    };

    //扩展操作

    // 【2】继承自Stream ,为了继承Stream的接口 (virtual Read...)
    class CryptoStream: public Stream {
    // FileStream / NetworkStream / MemoryStream
    // 运行时依赖
    // 【1】与Stream类组合,实现功能
    Stream* stream;//...

    public:
    CryptoStream(Stream* stm):stream(stm){
    }

    virtual char Read(int number){
    //额外的加密操作...
    stream->Read(number);//读文件流
    }
    virtual void Seek(int position){
    //额外的加密操作...
    stream::Seek(position);//定位文件流
    //额外的加密操作...
    }
    virtual void Write(byte data){
    //额外的加密操作...
    stream::Write(data);//写文件流
    //额外的加密操作...
    }
    };


    class BufferedStream : public Stream{
    Stream* stream;//...
    public:
    BufferedStream(Stream* stm):stream(stm){

    }
    //...
    };

    void Process(){
    //运行时装配 即编译时依赖优化成运行时依赖
    FileStream* s1=new FileStream();
    CryptoStream* s2=new CryptoStream(s1); // 加密 Stream* 接收 FileStream*
    BufferedStream* s3=new BufferedStream(s1); // 缓冲
    BufferedStream* s4=new BufferedStream(s2); // 加密 + 缓冲 Stream* 接收 CryptoStream*
    }

    // 如果多个子类有相同字段时,那么要将这个字段往上(往父类或者新建一个这种字段的中间类)提。 --马丁

最终

  • Decorator装饰类
  • 如果多个子类有相同字段时,那么要将这个字段往上(往父类或者新建一个这种字段的中间类)提。 –马丁
  • class Decorator : public Stream{Stream *stream}
    • stream*:用组合来代替继承实现多态
      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
      //业务操作
      class Stream{
      public
      virtual char Read(int number)=0;
      virtual void Seek(int position)=0;
      virtual void Write(char data)=0;
      virtual ~Stream(){}
      };

      //主体类
      class FileStream: public Stream{
      public:
      virtual char Read(int number){
      //读文件流
      }
      virtual void Seek(int position){
      //定位文件流
      }
      virtual void Write(char data){
      //写文件流
      }
      };

      class NetworkStream :public Stream{
      public:
      virtual char Read(int number){
      //读网络流
      }
      virtual void Seek(int position){
      //定位网络流
      }
      virtual void Write(char data){
      //写网络流
      }
      };

      class MemoryStream :public Stream{
      public:
      virtual char Read(int number){
      //读内存流
      }
      virtual void Seek(int position){
      //定位内存流
      }
      virtual void Write(char data){
      //写内存流
      }
      };

      //扩展操作类
      // DacoratorStream:要将CryptoStream以及BufferedStream的相同字段Stream*提出来。而放在Stream基类中发现不合适(主题类不需要Stream*字段)。因此,构造一个中间类。
      // 用组合的方式,引出对多态的支持
      class DecoratorStream: public Stream{
      protected:
      Stream* stream; //核心!!!
      DecoratorStream(Stream * stm):stream(stm){}
      };

      class CryptoStream: public DecoratorStream {
      public:
      CryptoStream(Stream* stm):DecoratorStream(stm){}
      virtual char Read(int number){
      //额外的加密操作...
      stream->Read(number);//读文件流 组合的动态特质
      }
      virtual void Seek(int position){
      //额外的加密操作...
      stream::Seek(position);//定位文件流
      //额外的加密操作...
      }
      virtual void Write(byte data){
      //额外的加密操作...
      stream::Write(data);//写文件流
      //额外的加密操作...
      }
      };


      class BufferedStream : public DecoratorStream{
      Stream* stream;//...
      public:
      BufferedStream(Stream* stm):DecoratorStream(stm){
      }
      //...
      };


      void Process(){
      //运行时装配
      FileStream* s1=new FileStream();
      CryptoStream* s2=new CryptoStream(s1);
      BufferedStream* s3=new BufferedStream(s1);
      BufferedStream* s4=new BufferedStream(s2);
      }

代码例子

  • 装饰器模式 Decorator
    • 通过子类实现功能增强的问题:为了增强现有类的功能,通过实现子类的方式,
    • 重写接口,是可以完成功能扩展的,但是代码中有太多的子类添加进来了
  • 车 A ,B ,C
  • 这些车,有的功能只有base , 有的有brake , hasten , boom 以及他们的组合
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
//
// Created by dell on 2022-03-28.
//


#include<iostream>

using namespace std;

// 车 A ,B ,C
// 这些车,有的功能只有base , 有的有brake , hasten , boom 以及他们的组合

class Car{
public:
virtual void show() = 0;
};

class ACar : public Car{
public:
void show() override
{
cout<<"A car : base , ";
}
};

class BCar : public Car{
public:
void show() override
{
cout<<"B car : base , ";
}
};


class CCar : public Car{
public:
void show() override
{
cout<<"C car : base , ";
}
};

class Decorator:public Car{
protected:
Decorator(Car *p):p_car(p){}
protected:
Car *p_car;
};

class ConcreteDecorator1 : public Decorator{
public:
ConcreteDecorator1(Car* p_car):Decorator(p_car){}
void show() override
{
p_car->show(); // 父类的show (原先就有的功能)
cout<<"hasten , "; // 添加功能
}

};

class ConcreteDecorator2 : public Decorator{
public:
ConcreteDecorator2(Car *p): Decorator(p){}
void show() override // 添加功能
{
p_car->show(); // 父类的show
cout<<"brake , ";
}
};

class ConcreteDecorator3 : public Decorator{
ConcreteDecorator3(Car *p): Decorator(p){}
void show() override // 添加功能
{
p_car->show();
cout<<"boom , ";
}
};




int main()
{
// 一个ACar 加上了装饰器1的功能hasten 之后就可以通过pA来调用这个加上了装饰器1功能的Acar对象
ConcreteDecorator1 *pA = new ConcreteDecorator1(new ACar());
pA->show();
cout<<endl;

// 一个BCar pB-> {装饰器1功能 + 装饰器2功能 + BCar对象}
ConcreteDecorator2 *pB = new ConcreteDecorator2(new ConcreteDecorator1(new BCar()));
pB->show();
cout<<endl;

// 不添加装饰器功能
CCar *pC = new CCar();
pC->show();
cout<<endl;
}

A car : base , hasten ,
B car : base , hasten , brake ,
C car : base ,

桥模式

  • 一个类中要实现两种不同维度的功能,就把这个类分成两个类,把两个不同维度的功能分开。
  • 把继承变组合实现多态
  • 几个子类中有公共字段,那么要把这个字段向上提。

    动机

  • 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度乃至多个纬度的变化。
  • 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?

定义

  • 抽象部分(业务功能)实现部分(平台实现)分离,使它们都可以独立地变化。

结构

要点总结

  • Bridge模式使用s“对象间的组合关系”s解耦了抽象和实现之间固 有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”他们。

  • Bridge模式有时候类似于多继承方案,但是多继承方案往往违背 单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。

  • Bridge模式的应用一般在“两个非常强的变化维度”,有时一个 类也有多于两个的变化维度,这时可以使用Bridge的扩展模式。

    重构

  • 初始

  • 要实现的类:1+n+n*m

    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
    class Messager{
    public:
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;

    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;

    virtual ~Messager(){}
    };


    //平台实现

    class PCMessagerBase : public Messager{
    public:

    virtual void PlaySound(){
    //**********
    }
    virtual void DrawShape(){
    //**********
    }
    virtual void WriteText(){
    //**********
    }
    virtual void Connect(){
    //**********
    }
    };

    class MobileMessagerBase : public Messager{
    public:

    virtual void PlaySound(){
    //==========
    }
    virtual void DrawShape(){
    //==========
    }
    virtual void WriteText(){
    //==========
    }
    virtual void Connect(){
    //==========
    }
    };



    //业务抽象

    class PCMessagerLite : public PCMessagerBase {
    public:

    virtual void Login(string username, string password){

    PCMessagerBase::Connect();
    //........
    }
    virtual void SendMessage(string message){

    PCMessagerBase::WriteText();
    //........
    }
    virtual void SendPicture(Image image){

    PCMessagerBase::DrawShape();
    //........
    }
    };



    class PCMessagerPerfect : public PCMessagerBase {
    public:

    virtual void Login(string username, string password){

    PCMessagerBase::PlaySound();
    //********
    PCMessagerBase::Connect();
    //........
    }
    virtual void SendMessage(string message){

    PCMessagerBase::PlaySound();
    //********
    PCMessagerBase::WriteText();
    //........
    }
    virtual void SendPicture(Image image){

    PCMessagerBase::PlaySound();
    //********
    PCMessagerBase::DrawShape();
    //........
    }
    };


    class MobileMessagerLite : public MobileMessagerBase {
    public:

    virtual void Login(string username, string password){

    MobileMessagerBase::Connect();
    //........
    }
    virtual void SendMessage(string message){

    MobileMessagerBase::WriteText();
    //........
    }
    virtual void SendPicture(Image image){

    MobileMessagerBase::DrawShape();
    //........
    }
    };


    class MobileMessagerPerfect : public MobileMessagerBase {
    public:

    virtual void Login(string username, string password){

    MobileMessagerBase::PlaySound();
    //********
    MobileMessagerBase::Connect();
    //........
    }
    virtual void SendMessage(string message){

    MobileMessagerBase::PlaySound();
    //********
    MobileMessagerBase::WriteText();
    //........
    }
    virtual void SendPicture(Image image){

    MobileMessagerBase::PlaySound();
    //********
    MobileMessagerBase::DrawShape();
    //........
    }
    };


    void Process(){
    //编译时装配
    Messager *m =
    new MobileMessagerPerfect();
    }

  • 重构后

  • 1+n+m

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
class Messager{
protected:
MessagerImp* messagerImp;//...
public:
virtual void Login(string username, string password)=0;
virtual void SendMessage(string message)=0;
virtual void SendPicture(Image image)=0;

virtual ~Messager(){}
};

class MessagerImp{
public:
virtual void PlaySound()=0;
virtual void DrawShape()=0;
virtual void WriteText()=0;
virtual void Connect()=0;

virtual ~MessagerImp(){}
};


//平台实现 n
class PCMessagerImp : public MessagerImp{
public:

virtual void PlaySound(){
//**********
}
virtual void DrawShape(){
//**********
}
virtual void WriteText(){
//**********
}
virtual void Connect(){
//**********
}
};

class MobileMessagerImp : public MessagerImp{
public:

virtual void PlaySound(){
//==========
}
virtual void DrawShape(){
//==========
}
virtual void WriteText(){
//==========
}
virtual void Connect(){
//==========
}
};



//业务抽象 m

//类的数目:1+n+m

class MessagerLite :public Messager {
public:
virtual void Login(string username, string password){
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->DrawShape();
//........
}
};



class MessagerPerfect :public Messager {
public:
virtual void Login(string username, string password){
messagerImp->PlaySound();
//********
messagerImp->Connect();
//........
}
virtual void SendMessage(string message){
messagerImp->PlaySound();
//********
messagerImp->WriteText();
//........
}
virtual void SendPicture(Image image){
messagerImp->PlaySound();
//********
messagerImp->DrawShape();
//........
}
};

void Process(){
//运行时装配
MessagerImp* mImp=new PCMessagerImp();
Messager *m =new MessagerLite(mImp); // 实现 PCMessageImp平台 + MessagerLite业务 组合
}