桥模式

设计模式之 桥模式

本文介绍 桥 模式,参考了 https://www.bilibili.com/video/BV1Yr4y157Ci

目的

由于某些类型的固有实现逻辑,使得它们具有多个变化的纬度。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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() {}
};

那么我们可能会需要考虑很多平台的实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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() {}
};

我们可能要推出精简版,或者完美版

 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
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();
        // ...
    }
};
 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
class MobileMessagerLite : public PCMessagerBase {
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 PCMessagerBase {
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();
        // ...
    }
};

那么我使用时就需要

1
2
3
void Process() {
    Messager *m = new MobileMessagerPerfect();
}

如果我们的抽象多了,那么类的数目又会增加很快。何况这些类里面重复的东西又很多。

如果我们使用装饰器模式中的继承转为组合,会好吗?可以。

我们可以合并 MessagerLite 类 和 MessagerPerfect 类,但会出现问题,因为两个 fooBase 的基类有问题,它是一个抽象类,因为没有全部实现基类接口,所以问题出现在 Messager 类上。参考如下代码

 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
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 MessagerLite {
    Messager* messager;
public:
    virtual void Login(string username, string password) {
        messager->Connect();
        // ...
    }
    virtual void SendMessage(string message) {
        messager->WriteText();
        // ...
    }
    virtual void SendPicture(Image image) {
        messager->DrawShape();
        // ...
    }
};

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

我们可以把它拆开,然后再正确的继承

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

class MessagerImpl {
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;
    virtual ~MessagerImpl() {}
};

class PCMessagerBase : public MessagerImpl {
public:
    virtual void PlaySound() {}
    virtual void DrawShape() {} 
    virtual void WriteText() {}
    virtual void Connect() {}
};

class MobileMessagerBase : public MessagerImpl {
public:
    virtual void PlaySound() {}
    virtual void DrawShape() {} 
    virtual void WriteText() {}
    virtual void Connect() {}
};

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

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

之后可以再提一次:

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

class MessagerImpl {
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;
    virtual ~MessagerImpl() {}
};

class PCMessagerImpl : public MessagerImpl {
public:
    virtual void PlaySound() {}
    virtual void DrawShape() {} 
    virtual void WriteText() {}
    virtual void Connect() {}
};

class MobileMessagerImpl : public MessagerImpl {
public:
    virtual void PlaySound() {}
    virtual void DrawShape() {} 
    virtual void WriteText() {}
    virtual void Connect() {}
};

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

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

此外修改一下构造函数即可,委托给父类。

1
2
MessagerImpl* imp = new PCMessagerImpl();
Messager* m = new MessagerLite(imp);

桥模式

将抽象部分(业务)与实现部分(平台实现)分离,使得它们可以独立变化。

桥模式

Licensed under CC BY-NC-SA 4.0
最后更新于 Mar 01, 2024 00:00 UTC