设计模式--桥模式
考虑要设计一个Messager模块,这个模块要实现如下功能
那么最直观的设计如下 class Messager { public: virtual void Login(string userName,string password) = 0; virtual void SendMessage(string message) = 0; virtual void PlaySound() = 0; virtual void DrawShape() = 0; virtual ~Message() {} }; ? 然后呢,我们这个Messager要实现跨平台的功能,要在PC平台和手机平台都能适用。然而对于PC和Mobile来说,唯一有区别的地方只有播放声音和画图这些与平台相关的函数不同,而登录、发送消息这些业务功能是相同的,所以你可能会设计出如下的两个类: class PCMessagerBase : public Messager { virtual void PlaySound() { /*******/ } virtual void DrawShape() { /*******/ } }; class MobileMessagerBase : public Messager { virtual void PlaySound() { /*******/ } virtual void DrawShape() { /*******/ } }; ? 接下来继续考虑在同一个平台要推出两个不同版本的Messager,一个是精简版,一个是完美版。比如说精简版的在登录的时候不会播放声音和显示图片,而完美版的则支持这两个功能。其设计可能如下: class PCMessagerLite : public PCMessagerBase { virtual void Login(string userName,string password) { /******/ } virtual void SendMessage() { /*******/ } }; class PCMessagerPerfect : public PCMessagerBase { virtual void Login(string userName,string password) { PCMessageBase::PlaySound(); PCMessageBase::DrawShape(); } virtual void SendMessage() { PCMessageBase::PlaySound(); PCMessageBase::DrawShape(); } } class MobileMessagerLite : public MobileMessagerBase { virtual void Login(string userName,string password) { /******/ } virtual void SendMessage() { /*******/ } }; class MobileMessagerPerfect : public MobileMessagerBase { virtual void Login(string userName,string password) { MobileMessageBase::PlaySound(); MobileMessageBase::DrawShape(); } virtual void SendMessage() { MobileMessageBase::PlaySound(); MobileMessageBase::DrawShape(); } } ? 那么到目前为止,类的结构图如下 ? 这么设计有什么缺点呢?缺点是代码重复性太大了。这种重复是一种结构性的重复。你仔细观察观察MobileMessagerPerfect和PCMessagerPeferct这两个类中Login和SendMessage的实现,会发现他们的流程是一模一样的,都是播放声音,显示登录画面,登录。不同的只是因为平台导致的播放声音和登录画面的实现不同。 ? 那么有什么改进的方法呢? 你可以发现在Perfect类的Login中的PlaySound和DrawShape可以追溯到同一个虚函数调用。如果你知道装饰者模式的话,那么你很快的可以想到改进的方法是将PCMobildBase作为一个类的字段去组合它,而不是去继承它 class PCMessagePerfect { 通过message->PlaySound()来调用。同理MobildMessagePerfect中设计一个MobileMessageBase*字段。但是如果都申明为一个具体平台的Base字段的话,程序又写的太死了,所以你又发现可以将这个类的字段申明为Message*,然后在将来要构造Perfect对象的时候传进去一个具体的Base对象。但是现在问题又来了,现在*Base对象是个抽象类,是无法new出对象的。(Login,SendMessage等方法没有实现) 那么问题的根源是什么?原因在是Message类中,你把业务逻辑(Login,SendMessage)和平台实现(PlaySound,DrawShap)混合到一起了,这样做是很不合适的,应该将他们拆分开。 最终的类设计应该如下 class Message { Login,SendMessage } // 业务功能部分class MessageImp { PlaySound,DrawShap } // 平台实现部分class PCMessageBase : MessageImp {} // 具体的平台实现class PCMessagePerfect : Message { // 继承Message的业务功能部分 MessageImp* messageImp; // 组合得到Message的平台功能部分} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |