博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
桥接模式-通俗的理解(转)
阅读量:2434 次
发布时间:2019-05-10

本文共 4869 字,大约阅读时间需要 16 分钟。

本文来自:崔成龙博客专栏。转载请注明出处:
    软考上午题终于考完了。三个赶考者都感觉不错。检查了2遍,提前30分钟都出来了 。
    小A,小B,小C楼下碰头,相视一笑,轻松之感溢于言表。遂决定去吃面,以犒劳自己的肚子。
   “老板,我要西红柿鸡蛋面!”,“尖椒炸酱面!”,“苏格兰打卤面!”。。。。。。“好嘞!”
    面快出锅了,“哎哎,老板,怎么我的面跟他的面一样啊,就是换了一下卤?”往面里放卤的服务员翻了小B一眼,不搭理。旁边那个年长点的师傅笑了笑,说道“小兄弟儿,这你就不懂了吧。其实面都是一样的,只是换一下卤罢了。”“哦哦,原来如此啊。”小B灰溜溜得端起面来跑开了。。。
    面毕,小B实在是咽不下这口气。就想在小C那儿“捞回点儿本来”。
    “小C,面吃的怎么样啊?”小B阴阳怪气的问道。
    小C看着小B的表情,觉得有点不对劲,自己是不是又要上当了,但是又想不出来自己哪留有什么“把柄”,然后就答道,
    “还,还行吧,问这干嘛??”
    “嘿,你怕什么呀。我考一个关于吃面的题目”
    “嗨,我还以为什么呢,随便考吧,哥是来者不拒。”小C心里想到,就你那智商,能出什么样的难题呢,等着被鄙视吧。
    “你感觉自家煮面和饭馆煮面有什么不同?”
    “这还用问!感觉不同呗。自己煮面,自己累死了还得做饭,又是炒卤,又是煮面的,最低也得折腾半小时吧。饭馆多好啊,只要吆喝一声,人家都给你做好,端到你面前了。而且速度超快的。连这个都不知道。也对,就你那智商,好吧,我原谅你,哈哈哈哈”
    “哼,别笑得太早了。同样是面?你说为什么感觉不同啊”
    “呃,这个嘛,嗯,让我想想”小C装傻了。。。
    “哈,有点意思哎。我给你说说看看对不。”小A憋不住了。接着说道,
    “刚才小C说了,自家煮面,你必须自己做卤,自己煮面。每次想吃面的时候,这两步都是少不了的。但是面馆不一样啊。饭馆卤都是提前做好的。你点了面后,面馆给你煮面,然后加上你要的卤不就OK了吗!而且速度超快。比自己做饭省事多了。”
    “哦~,原来如此。”
    “我说那会那个服务员像看白痴的一样看我呀。”小B嘀咕道
    “what,what!!原来你被吃瘪了啊,哈哈”小C得意得捧腹大笑。
    小A眼睛一转,对即将要发飙的小B说道,
    “既然是你提出来的,你说说饭馆为什么要这么做呢?”
    “呃,嗯,,,,我想,应该是为了更快捷,方便地方便用户,同时提高自己的效率吧。”
    “还有没有别的?”
    小B想了半天,摇来摇头,“想不到了”
    “提示一点,面馆在增加新类型面的时候,是怎么做的?”
    “哦~~,我知道了,因为面差不多是一样的,只需要准备卤就行了。”
    “嗯,对的。其实面也是有不同的。比如说宽面,拉面,圆面。这样一组合,新的类型的面就出炉了。”
    “原来面馆里也有这么大学问啊。”
    “那是当然。365行,行行出状元啊。先不说这个了,既然说道这个面了,那你用面向对象写写刚才我们讨论的这件事儿吧。”
    “好。我试试吧”小B自信道。
     既然是面向对象,那么先把类找出来吧。首先有原料(Material),下分为面(Noodles)和卤(Halogen)。面有宽面条(WideNoodles),窄面条(NarrowNoodles)等多种类型,卤菜有西红柿鸡蛋卤(TomatoAndEgg),茄子豆瓣酱(AubergineBeanPaste)等多种卤菜。  西红柿鸡蛋面类(TomatoEggNoodles)为西红柿鸡蛋卤和宽面构成,而苏格兰打卤面(ScotlandNoodles)则是有茄子 豆瓣酱和窄面构成的。
先画出UML图:
uml图1.0版

    “看看怎么样啊”,小B得瑟的说道。
    “你有没有考虑代码的实现呢?”小A用看白痴的眼神扫了小B一眼,“除了C++,还有几个面向对象的有多继承啊!”
    “呃,这个,失误失误,我马上改!”
    “别急啊,还有错误呢,西红柿鸡蛋面有两部分构成,那肯定是用聚合或者是组合啊,不应该用继承的”小A提醒道。
    “哦,原来如此,我说怎么感觉有点不对劲呢,等着吧”
    5分钟过后。。。
    “哦,终于出来了,看看这次怎么样啊。”
uml图2.0.版

    “西红柿鸡蛋面和苏格兰打卤面的组成关系也画出来了。嗯不错,不过还有一点不对劲。假如我现在加一个新类型的面——西红柿鸡蛋卤面(窄面),你怎么加”
    “那就从面条类里泛化一个西红柿鸡蛋卤面(窄面)类,然后再在它上面加上与西红柿鸡蛋卤和窄面的组合关系”
    “那如果我现在面馆开10个分面馆,每个分面馆新增10样类,你是不是这100种面都要重新添加一遍面和卤的组合关系吧。”
    “那我还不得累死啊,这种活干不得!”小B惶恐的说道。
    “不管累,当你画出UML图的时候,能把你乱死。成品面与具体的面类型和卤菜类型的耦合性就太高了。想办法松散这些耦合。”
    “那怎么办呢?”小B焦急的问道。
    “呃,提醒你一点,你先对比一下你这两版UML各自的特点。”
    “第一幅图继承关系比较明显,第二幅图则利用了组合关系,使其继承关系简单化了”
    “如果你把这两个图合成一个图呢?”
    “这,这,怎么合啊。”
    “看来还得我出马啊,看着昂”
UML图3.0版

    “不管什么打卤面,都抽象于卤面类。卤面类由面条类和卤菜类组成。面条类和卤菜类都有各自的子类。”
    “这个图好面熟啊。让我想想昂。哦,对了,这不是桥接模式吗!”
    “是的,不过这样做有什么好处呢?”
    “这样做有几个好处,第一,松散耦合。具体的打卤面不再与具体的面类型和卤类型直接关联,松散了它们之间的耦合;第二,在变化方面,具体的打卤面, 具体的面类型和具体的卤类型各自的变化,互不影响”
    “这样我在开分面馆的时候就不用画那么多关系了,添加新类型的打卤面不再成为难事。果然很厉害。哈哈哈哈”小B得瑟的笑着,好像他真的要开面馆似的。
    “对头!这就满足了开闭原则,不用去修改,只需要添加即可。实例化具体的打卤面时,在客户端指定一下要哪种面,哪个卤即可。”小A接着说,
    “其实这里面最重要的是利用聚合组合关系,松散了耦合,使得抽象不再依赖于具体,而具体要依赖于抽象。”
    “哦,对哦。设计模式果然牛X。”
    “代码留在晚上再写吧,早点休息,下午还有考试呢!”小A看着一脸丫丫的小B,提醒道。
    “哦哦,差点忘了还有考试了。希望下午碰到桥接模式,那我就。。。”小B继续陷入丫丫ing。
    小A摇摇头,不再理睬小B,推开霸占自己床铺的小C,休息去了。
 

  面条类及子类

[csharp] 
  1. #region  面条类及子类  
  2.   
  3. /// <summary>  
  4. /// 面条类  
  5. /// </summary>  
  6. public abstract  class Noodles  
  7. {  
  8.     public Noodles()   
  9.     {  
  10.     }  
  11.   
  12.     /// <summary>  
  13.     /// 获取面类型名称  
  14.     /// </summary>  
  15.     /// <returns></returns>         
  16.     public abstract string GetName();  
  17.   
  18. }  
  19.   
  20. /// <summary>  
  21. ///  窄面条  
  22. /// </summary>  
  23. public class  NarrowNoodles:Noodles  
  24. {  
  25.     public NarrowNoodles()  
  26.     {  
  27.     }  
  28.   
  29.     public override string GetName()  
  30.     {  
  31.         return "窄面条";  
  32.     }  
  33. }  
  34.   
  35. /// <summary>  
  36. /// 宽面条  
  37. /// </summary>  
  38. public class WideNoodles : Noodles  
  39. {  
  40.     public WideNoodles()  
  41.     {  
  42.     }  
  43.     public override string GetName()  
  44.     {  
  45.         return "宽面条";  
  46.     }  
  47. }  
  48.  
  49. #endregion  

 卤菜类及子类

[csharp] 
  1. #region 卤菜类及子类  
  2.   
  3. /// <summary>  
  4. /// 卤菜类  
  5. /// </summary>  
  6. public abstract class Halogen  
  7. {  
  8.     public Halogen()  
  9.     {  
  10.     }  
  11.   
  12.     /// <summary>  
  13.     /// 获取卤菜名称  
  14.     /// </summary>  
  15.     /// <returns></returns>  
  16.     public abstract string GetName();  
  17. }  
  18.   
  19. /// <summary>  
  20. /// 西红柿鸡蛋卤  
  21. /// </summary>  
  22. public class TomatoAndEgg : Halogen  
  23. {  
  24.     public TomatoAndEgg()  
  25.     {  
  26.     }  
  27.     public override  string GetName()  
  28.     {  
  29.         return "西红柿鸡蛋卤";  
  30.     }  
  31. }  
  32.   
  33. /// <summary>  
  34. /// 茄子豆瓣酱  
  35. /// </summary>  
  36. public class AubergineBeanPaste:Halogen  
  37. {  
  38.     public AubergineBeanPaste()  
  39.     {  
  40.     }  
  41.     public override string GetName()  
  42.     {  
  43.         return "茄子豆瓣酱";  
  44.     }  
  45. }  
  46.  
  47.  
  48.  
  49.  
  50. #endregion  

 

打卤面类及子类 

[csharp] 
  1. #region 打卤面类及子类  
  2. /// <summary>  
  3. /// 打卤面类  
  4. /// </summary>  
  5. public class NoodlesAndHalogen  
  6. {  
  7.     protected string name;  
  8.     protected Noodles noodles;  
  9.     protected Halogen halogen;  
  10.   
  11.     public NoodlesAndHalogen(string name, Noodles noodles, Halogen halogen)  
  12.     {  
  13.         this.name=name;  
  14.         this.noodles = noodles;  
  15.         this.halogen = halogen;  
  16.     }  
  17.   
  18.     /// <summary>  
  19.     /// 获取名称及成分  
  20.     /// </summary>  
  21.     public void  GetName()  
  22.     {  
  23.         Console.WriteLine("我是"+name+",由"+noodles.GetName () +"和"+halogen.GetName ()+"组成");  
  24.     }  
  25. }  
  26.   
  27.   
  28. /// <summary>  
  29. /// 西红柿鸡蛋面  
  30. /// </summary>  
  31. public class TomatoEggNoodles : NoodlesAndHalogen   
  32. {  
  33.     public TomatoEggNoodles(string name, Noodles noodles, Halogen halogen)  
  34.         : base(name, noodles, halogen)  
  35.     {  
  36.     }  
  37.          
  38. }  
  39.   
  40. /// <summary>  
  41. /// 苏格兰打卤面  
  42. /// </summary>  
  43. public class ScotlandNoodles : NoodlesAndHalogen  
  44. {  
  45.     public ScotlandNoodles(string name, Noodles noodles, Halogen halogen)  
  46.         : base(name, noodles,halogen)  
  47.     {  
  48.     }  
  49.          
  50. }  
  51.   
  52. region  

 客户端代码: 

[csharp] 
  1. static void Main(string[] args)  
  2. {  
  3.     NoodlesAndHalogen n1=new TomatoEggNoodles("西红柿鸡蛋面(宽面)",new WideNoodles(),new TomatoAndEgg() );  
  4.     n1.GetName();  
  5.     NoodlesAndHalogen n2 = new ScotlandNoodles("苏格兰打卤面(窄面)"new NarrowNoodles(), new AubergineBeanPaste());  
  6.     n2.GetName();  
  7.     Console.Read();  
  8. }  

 运行结果:

你可能感兴趣的文章
换行符
查看>>
O2O
查看>>
想起一句话:”多加一层,就可以把问题解决了“
查看>>
PostgreSQL Page页结构解析(7)- B-Tree索引存储结构#3
查看>>
企业文化和价值观
查看>>
推荐书籍:金字塔原理
查看>>
基础存储知识
查看>>
PostgreSQL 源码解读(37)- 查询语句#22(查询优化-grouping_plan...
查看>>
PostgreSQL 源码解读(44)- 查询语句#29(等价类相关数据结构)
查看>>
PostgreSQL 源码解读(48)- 查询语句#33(query_planner函数#9)
查看>>
PostgreSQL 源码解读(45)- 查询语句#30(query_planner函数#6)
查看>>
PostgreSQL 源码解读(47)- 查询语句#32(query_planner函数#8)
查看>>
PostgreSQL 源码解读(17)- 查询语句#2(查询优化基础)
查看>>
Windows Vista内置趣味实用工具大搜罗(转)
查看>>
FreeBSD安装文件系统(转)
查看>>
最简单FreeBSD网关方案(转)
查看>>
Windows 98 多用户的管理(转)
查看>>
更改Windows XP 的日期和时间(转)
查看>>
windows2000中的“秘密武器”(三)(转)
查看>>
Linux程序应用开发环境和工具经验谈(转)
查看>>