问题提出
假设现在需要实现一个跨平台的聊天系统,其中会包括实现具体业务逻辑的方法(如登录、发送文字、发送图片)和与平台相关的方法(如建立连接、播放声音、显示文字、显示图片)。
1.0 版本
根据上面的需求,我们可以定义一个 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 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
| class Messager { public: virtual void Login(string username, string password) = 0; virtual void SendMessage(string message) = 0; virtual void SendPicture(string 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 PCMessager : public PCMessagerBase { public: virtual void Login(string username, string password) { PCMessagerBase::Connect(); } virtual void SendMessage(string message) { PCMessagerBase::WriteText(); } virtual void SendPicture(string image) { PCMessagerBase::DrawShape(); } };
class MobileMessager : public MobileMessagerBase { public: virtual void Login(string username, string password) { MobileMessagerBase::Connect(); } virtual void SendMessage(string message) { MobileMessagerBase::WriteText(); } virtual void SendPicture(string image) { MobileMessagerBase::DrawShape(); } };
int main() { Messager * messager = new MobileMessager; delete messager; return 0; }
|
这样算是暂时满足了需求,但很明显可以看出问题,PC 平台和 Mobile 的业务逻辑并不存在太大的区别,但我们却用了两个类来分别实现这两个类似的功能,也就是说,每增加一个新的平台,不止要重新考虑平台相关的代码,就连业务逻辑代码也不得不新建一个类来实现。
如果待实现的平台有 n 个,需要实现的类的个数为 (2n + 1) 个。如果这样还是可以忍耐的话,那下面的需求变化就会导致巨大的灾难。
2.0 版本
新的需求来了,现在要为每个平台分成精简版和完整版两个版本发布,它们之间不同的也是业务逻辑,可以写出下面的代码。
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
| class Messager { public: virtual void Login(string username, string password) = 0; virtual void SendMessage(string message) = 0; virtual void SendPicture(string 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(string image) { PCMessagerBase::DrawShape(); } };
class PCMessagerPerfect : public PCMessagerBase { public: virtual void Login(string username, string password) { PCMessagerBase::Connect(); PCMessagerBase::DrawShape(); } virtual void SendMessage(string message) { PCMessagerBase::WriteText(); PCMessagerBase::PlaySound(); } virtual void SendPicture(string image) { PCMessagerBase::DrawShape(); PCMessagerBase::PlaySound(); } };
class MobileMessagerLite : public MobileMessagerBase { public: virtual void Login(string username, string password) { MobileMessagerBase::Connect(); } virtual void SendMessage(string message) { MobileMessagerBase::WriteText(); } virtual void SendPicture(string image) { MobileMessagerBase::DrawShape(); } };
class MobileMessagerPerfect : public MobileMessagerBase { public: virtual void Login(string username, string password) { MobileMessagerBase::Connect(); MobileMessagerBase::DrawShape(); } virtual void SendMessage(string message) { MobileMessagerBase::WriteText(); MobileMessagerBase::PlaySound(); } virtual void SendPicture(string image) { MobileMessagerBase::DrawShape(); MobileMessagerBase::PlaySound(); } };
int main() { Messager * messager = new MobileMessagerLite; delete messager; }
|
代码的类图如下:

现在,灾难发生了,上面的代码仅有两个平台,两个版本,最终需要实现 1+2+2×2 = 7 个类,如果平台和版本的数量继续增加,当有 n 个平台,每个平台需要 m 个版本时,需要实现的类的个数为 1+n+n×m 个,这时候就需要对代码进行重构了。
3.0 版本
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
| class MessagerImp;
class Messager { protected: MessagerImp *messagerImp; public: Messager(MessagerImp *mImp) : messagerImp(mImp) {
} virtual void Login(string username, string password) = 0; virtual void SendMessage(string message) = 0; virtual void SendPicture(string 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() {
} };
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() { } };
class MessagerLite : public Messager { public: MessagerLite(MessagerImp *mImp) : Messager(mImp) {} virtual void Login(string username, string password) { messagerImp->Connect(); } virtual void SendMessage(string message) { messagerImp->WriteText(); } virtual void SendPicture(string image) { messagerImp->DrawShape(); } };
class MessagerPerfect : public Messager { public: MessagerPerfect(MessagerImp *mImp) : Messager(mImp) {} virtual void Login(string username, string password) { messagerImp->Connect(); messagerImp->DrawShape(); } virtual void SendMessage(string message) { messagerImp->WriteText(); messagerImp->PlaySound(); } virtual void SendPicture(string image) { messagerImp->DrawShape(); messagerImp->PlaySound(); } };
int main() { MessagerImp *mImp = new PCMessagerImp; Messager *msg = new MessagerLite(mImp);
delete msg; delete mImp; return 0; }
|
这边是用桥模式实现的方案,其类层次结构图如下:

总结
