标签: 设计模式初涉
我有故事,你有酒吗?这年头写个技术文不讲个故事都不行,行,我讲;
还有发现很多的技术博文都开始有喜欢往文中插入几个表情的趋势了,
但是你真的插的姿势对了吗?这种事情不是随便插的,来来来,给你
见识下如何在适当的场景插入适当的表情以让读者感觉到易可赛艇,
本文以讲故事插表情为主,讲述桥接模式为辅,多图预警,
简书上排版可能有些问题,最佳排版可见:
https://www.zybuluo.com/coder-pig/note/643756
我就喜欢这样光明正大的开着我的托马斯小火车,污污污
![](http://static.zybuluo.com/coder-pig/ykuh2oqaxswvegvre8djwg0y/image_1b87hu8ppqfb5n61lvn18mrnfie7.png)
场景引入
在之前的章节中,我们都知道小猪开家奶茶店,凭借着独特
的奶茶制作工艺,每天都吸引了一堆吃货在门口排队。每天基本
都是坐着收钱,但是喜欢折腾的小猪并不只满足于卖奶茶和小吃,
他一直在寻求着新的盈利点。一天没事,他打开了“丑团外卖”,
看着别人做餐饮的怎么玩,咦,有加奶茶店竟然做起了卖煲仔
饭的副业,打着“新品煲仔饭新鲜出炉,买饭送饮料”的广告口号,
再看下销量,还不赖,饭 + 饮料 + 小吃,能再从饭里面捞一笔,
但是做什么饭好呢?思前想后还是做技术水平最低的扒类,去市场
买好扒,买些酱料腌制下,然后丢铁板上一煎,然后配点饭或者
意粉,成本也就10来块,妥妥地卖30块一份,23333
![](http://static.zybuluo.com/coder-pig/ojqyhxdjx99mlpra0u97zszv/%E6%9C%AA%E5%91%BD%E5%90%8D.jpg)
嘿嘿,打算卖这几样东西:
- 牛扒
- 猪扒
- 牛扒饭
- 猪扒饭
- 牛扒意粉
- 猪扒意粉
接着按照套路来,我们撸下代码,不用Bridge模式的一般玩法:
先建立一个扒的父类:Steak.java
![](http://static.zybuluo.com/coder-pig/laz19wczfk4eaa8e9pe9mueu/1.png)
接着继承这个扒类编写牛扒与猪扒子类
![](http://static.zybuluo.com/coder-pig/637gncmijl6i5uldbpnb1cp2/2.png)
![](http://static.zybuluo.com/coder-pig/0clal7g6bfh2t199mu3cp4g4/3.png)
再接着继承猪扒和牛扒,写出四个子类
![](http://static.zybuluo.com/coder-pig/hxtaw9p7ca0j701rfs39qjo9/4.png)
![](http://static.zybuluo.com/coder-pig/4b0kwdi4t0meld3tedq3zcd7/5.png)
![](http://static.zybuluo.com/coder-pig/ttwukuwv3xqbc4e5xe1ef4m9/6.png)
![](http://static.zybuluo.com/coder-pig/qqx8tbutasdh9ojcpjg1xm9g/7.png)
准备就开卖了,写一个餐馆类来卖扒:
![](http://static.zybuluo.com/coder-pig/gprsueixop58yinuka1n7he9/8.png)
输出结果:
![](http://static.zybuluo.com/coder-pig/nh0v2za9o4iyj8a813fgyyps/9.png)
可以,老铁,没毛病,就这样开始搞事情了~
![](http://static.zybuluo.com/coder-pig/s81t7dr90ci4nf12u5kxg4jr/83ee25738bd4b31c248532f48ed6277f9f2ff8cc.jpg)
问题初现
新品推出,肯定是搞吃扒送饮料的套路,由此吸引了一大波贪小便宜
的吃货,人多了,要求也多了,吃货反馈最多的问题是:
没有鸡扒,这不清真!
视顾客为上帝的小猪,肯定是急急脚把鸡扒加上:
![](http://static.zybuluo.com/coder-pig/s7h81h9qg90c41wbpf9sy8mz/10.png)
![](http://static.zybuluo.com/coder-pig/7wrrcni7lyyoy1u9ia1o4epb/11.png)
![](http://static.zybuluo.com/coder-pig/yjk0oj8zht2u3wsd3w8upcma/12.png)
然后调用下就好,又一次解决了吃货的需要,小猪感到很愉悦。
鸡扒是有了,然后吃货们又说想吃鱼扒,照葫芦画瓢又得
继承,写三个类,有些繁琐,小猪开始意识到可能有些问题,
但是因为懒和拖拉,还是默默接受了没毛病这个设定,然后
沿用原先的套路把鱼扒也加上了。
![](http://static.zybuluo.com/coder-pig/5g6hx3s2kv536dt6q61frulx/86c1de628535e5ddff1604907fc6a7efce1b624e.jpg)
问题又现
此时的小猪正悠闲的玩着王者农药,他似乎没有意思到逐渐
向他靠近的挑战。店员小B走了过来:
对小猪说: "老板,客人想要羊扒。"
小猪此时正在打团,因为被打断导致了团灭,有些不悦的说道:
"那就加上啊,按照之前的鸡扒鱼扒套路玩啊,你怎么那么蠢?"
小B一脸尴尬的说道:客人觉得味道太单一,有的想要加番茄汁,
有的想要加黑椒汁...,我不知道该怎么办"
小猪突然意识到事态的严重性了,这得继承N次,建多少个类啊!
需要一个人静静,然后把手机递给了小B,语气凝重的说到:
"这把黄金上铂金的晋级赛,输了扣你半个月工资!"
然后扬长而去,小B看了看战绩:0:20:5?站在原地一脸懵逼~
![](http://static.zybuluo.com/coder-pig/xb8n5dgeltpflagkul5xsne4/x.png)
小猪一边走一边想,按照原有的套路,加上汁又得
加上N多的类,如果顾客又想加配菜呢,这是要GG啊,
这耦合度太高了,旧套路必须推翻,得想个新的套路!
![](http://static.zybuluo.com/coder-pig/105vrhvvcce9msbfhdd8pf0i/2017-01-20-e46fabf4067047a69916ed3d76e6b882.jpg)
走着走着来到一个没人的地方了,小猪左顾右盼确定
没人后,悄悄地把自己的手塞到裤裆中,反复翻动,似乎
在寻找着什么,然后掏出了不可描述的长18.4cm的...
欲望知后事如何请听下回分解~
读者老爷:下回个毛线,快把你这破车飚完!
![](http://static.zybuluo.com/coder-pig/b6mruqfh2n99wmmv20iorb58/2017-01-26-f0b99a230278cb6122d5c1a40c7ccec1.jpg)
好的,上回说到,小猪从裤裆里掏出了18.4cm长不可描述的东西,
这个到底是什么呢?为何小猪要找没人的角落才敢掏出来?
![](http://static.zybuluo.com/coder-pig/b04oyaltoa4wj3bzujxqh61l/2017-01-23-1b7e3a2d605b276a8736dd2ea5f34c6d.jpg)
此物看上去黑硬粗,离近一看才知道是:
《如何让孩子爱上设计模式》
黑色的封面,硬质书皮,粗体书名,长18.4cm * 宽13cm
不可描述是因为此书是编程界三十六道绝世功法中的
一本,一但被别人知道了,必然会引起杀身之祸,小猪
小猪虽然已经掌握了其中的二十三式中的前九式,但是
还是没有自保的能力,所以平日只能藏于裤裆之中,
在没人的地方才敢拿出来反复研读。
![](http://static.zybuluo.com/coder-pig/5w4zq2duh9o2i0dzyxo5hv02/2017-02-04-4f5b8313a323b58a879ebb4bc4034e68.png)
话说回来,小猪翻开《如何让孩子爱上设计模式》快速翻阅
着能够解决当前问题的设计模式,当翻到桥接模式的时候,
一段文字映入小猪的眼帘:
在软件系统中,某些类型由于自身的逻辑,它具有两个或
多个维度的变化,那么如何应对这种“多维度的变化”?
如何利用面向对象的技术来使得该类型能够轻松的沿着
多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
多维?维度变化?小猪不解,继续往下看,看到一句心法:
将抽象部分与实现部分分离,使得他们可以独立地进行变化!
把变化的因素都分离出来(抽象类),让他独立变化(继承),然后在程序运行时
动态地将抽象与实现部分组合起来。而多维桥接需要互相持有,
比如这里的扒类持有饭意粉,酱汁类持有扒类!如果再
加上配菜,就加多一个配菜类持有酱汁类!
没错,就是这样,小猪此刻犹如醍醐灌顶,灵魂附体,立马
飞身赶回店中,已经迫不及待的想用桥接模式来秀一波了。
桥接模式初显威风
回到店里的小猪就是一顿疯狂输出,把变化因素都抽取出来:
先抽配餐类,毕竟这个是可变的,可饭,可意粉,你喜欢还可以加河粉:
![](http://static.zybuluo.com/coder-pig/fklwadx57c9tdlcy8wrvfxsi/image_1b87d38sr1j4k1lg61kmr1vb81kov5d.png)
继承配餐类的饭和意粉
![](http://static.zybuluo.com/coder-pig/gyczcufifw8eb1ghobk6v7ty/image_1b87d3oqh1lan1tu81a8ektevp5q.png)
![](http://static.zybuluo.com/coder-pig/mfavhbz97si5evfpdro5ukhp/image_1b87d4m8j3mf227go317sgi5t67.png)
再抽扒类,也是可变的,可牛,可猪,可鸡,可鱼,可苟
![](http://static.zybuluo.com/coder-pig/6afoym2i84g8oq4uzwxufqda/image_1b87dqitt76qav9170d1rgn29u6k.png)
牛扒与猪扒
![](http://static.zybuluo.com/coder-pig/yw0a2tizwc67ztlbfu4nmy56/image_1b87ds393ev9u9riel67014g7e.png)
![](http://static.zybuluo.com/coder-pig/h73fzfhnkmm4ehbkenwb8zdb/image_1b87drc8ggm61tcdqb1lt9h0a71.png)
改良后的卖扒套路:
![](http://static.zybuluo.com/coder-pig/7m6lbn9nsuz8kihqi9o557uu/image_1b87dugup1a4n1rb41je65mhb3b7r.png)
输出结果:
![](http://static.zybuluo.com/coder-pig/kmo864xfmckl0sxtnft75fvd/image_1b87dutt81chs5695b7ofquqe88.png)
原先要的效果实现了,再加上鸡扒和羊扒又如何:
![](http://static.zybuluo.com/coder-pig/9jbia4ye3yi8bwhb4z3kft1h/image_1b87e5fbr127b11lhqtp14cmea8l.png)
![](http://static.zybuluo.com/coder-pig/2o9wyiyb2m6v18ssrhna15zq/image_1b87e6ng01ccdmuo1vgm149621r92.png)
![](http://static.zybuluo.com/coder-pig/jrdueg6nckp9lh04jpu1zegx/image_1b87e7c7ganq1rq41ebn1gr2ecg9f.png)
![](http://static.zybuluo.com/coder-pig/xo1rkl9n7z55p8sz0ywjqrgm/image_1b87e7nc517ad1ulkoob711dre9s.png)
就是这么简单,什么鱼扒,狗扒随便来,唰唰唰就加上了,
小猪表示无所畏惧!
桥接模式再显神威
正当小猪沾沾自喜的时候,店员小B急冲冲地跑进来喊道:
“小猪老板,前几天要加酱汁的顾客又来闹事啦!啊!啊!啊!”
小猪很淡定的说到:“莫方莫方,带我出去看看,我自能解决!”
刚出店门,小猪就被眼前的景象所惊呆了:
![](http://static.zybuluo.com/coder-pig/kjy5k5il06w6tinxducs8j98/1.gif)
![](http://static.zybuluo.com/coder-pig/ixwbrbujrtg73h9jivpgv5cy/2.jpg)
![](http://static.zybuluo.com/coder-pig/329b3s5yqmim4ews9rm9ysbt/1.gif)
![](http://static.zybuluo.com/coder-pig/j8utjz5ykhhdexxeshe4hi2d/3.jpg)
恢复了一下情绪后,小猪问到:“就是你们三个加酱汁是吧?”
跳舞的基佬:“是的,我们分别要黑椒汁,番茄汁和香草汁,今天
要是不给我们搞,我们就继续在这里跳舞,只要有空地,哪里都能跳尬舞!”
小猪微微一笑,说到:“呵呵,原来是砸场子的,今日倒要给你们看看我的本事!”
跳舞的基佬一惊:
![](http://static.zybuluo.com/coder-pig/sm7cpuudj8nmo8srytf991yi/4.jpg)
![](http://static.zybuluo.com/coder-pig/xear942gs91rn1vj9azaz1ip/5.jpg)
,然后开始疯狂操作了起来!
变化的是酱汁,把他抽取出来,持有扒类
![](http://static.zybuluo.com/coder-pig/lhop58da2m3mpehwrtzt595c/image_1b87esl366n5bqb1msvau25e8a9.png)
番茄汁,黑椒汁,还有香草汁
![](http://static.zybuluo.com/coder-pig/67cisrk8uuk2w61x37btvmnf/image_1b87etjsu1n7j1e4v2ormj5u3jam.png)
![](http://static.zybuluo.com/coder-pig/ely0osbk1u0xfk8ead9t1y89/image_1b87eu6m71u16pag1soj1g08f5tb3.png)
![](http://static.zybuluo.com/coder-pig/7ghpvsd9a0hyj8h888t4ctdk/image_1b87eup4ok6u17qa2jp1gehs5ebg.png)
接着是调用部分
![](http://static.zybuluo.com/coder-pig/xq65cfzxd7pv9na3axggkyze/image_1b87evgp8cto1u2tukta1n1eecbt.png)
输出结果:
![](http://static.zybuluo.com/coder-pig/g8xqs6b83m1i429lgnbca4dl/image_1b87f16of16gi13621u1c60f1d5oca.png)
![](http://static.zybuluo.com/coder-pig/ysdshkov821g2t5cl34kkjb0/image_1b8a26dlrndd1jcg50j2lo1s4ll.png)
跳舞基佬开始怂了,边说边退后道:"你...猪哥村夫,你敢..."
小猪哥义正言辞到:"住口,三只断脊之犬,也敢在我店门前狺狺狂吠"!
三个跳舞基佬发出“啊”的叫声后,应声倒地不起。
小猪补刀到:![](http://static.zybuluo.com/coder-pig/y8fq5u5y5i14mymuur35hvvi/6.gif)
围观群众无不拍手叫好,厉害厉害!
![](http://static.zybuluo.com/coder-pig/tfh606204xpnrngbr9igennv/10.gif)
戏看完了,围观群众也散了,大获全胜的小猪大摇大摆地走回店里,
而此时他却没发现,在暗处里站着一个人:
![](http://static.zybuluo.com/coder-pig/aqxpgnhgismu0syj8yg1lmtm/7.jpg)
“原来《如何让孩子爱上设计模式》的功法在你手上,呵呵”,
随之露出一抹冷笑,接着消失在空气中...
小猪突然觉得背后一凉,回头一看却发现空无一人:
![](http://static.zybuluo.com/coder-pig/uwjne401cwdjqwaoubwncc89/11.gif)
小猪安慰着说:“可能是心理作用吧!”,然后又继续玩农药了。
躲在暗处的人到底是谁呢?为什么她会知道小猪持有长18.4cm黑硬粗的
——《如何让孩子爱上设计模式》功法呢?是敌是友?是女是女?
小猪又会遇上怎样的危机呢?又会发生怎样的故事呢?
欲知后事如何,请听下回分解...
======= 本章完 =======
好的,故事听完了,接下来讲一波概念性的东西~
桥接模式的定义
桥接模式基于单一职责原则,如果系统中的类存在多个
变化的维度,通过该模式可以将这几个维度分离出来,
然后进行独立扩展。这些分离开来的维度,通过在抽象层
持有其他维度的引用来进行关联,就好像在两个维度间
搭了桥一样,所以叫桥接模式。
四个角色
Abstraction:抽象部分的接口。通常在这个对象里面,要维护一个实现部分
的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。
这个对象里面的方法,通常都是跟具体的业务相关的方法。Refined Abstraction:扩展抽象部分的接口,通常在这些对象里面,
定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中
定义的方法,也可能需要调用实现部分的对象来完成。Implementor:定义实现部分的接口,这个接口不用和Abstraction
里面的方法一致,通常是由Implementor接口提供基本的操作,而
Abstraction里面定义的是基于这些基本操作的业务方法,也就是说
Abstraction定义了基于这些基本操作的较高层次的操作。ConcreteImplementor:真正实现Implementor接口的对象。
UML类图
![](http://static.zybuluo.com/coder-pig/r563t5zz9qz5oy5zngs5ng2f/image_1b8a77ta0c4p1fq31l4m148hv1n12.png)
优缺点
优点:
- 实现了抽象和实现部分的分离,更好的可扩展性,动态切换实现,
- 很多情况下桥接模式可以替代多层继承方案,极大减少子类个数!
缺点:
- 增加系统的理解与设计难度,由于关联关系建立在抽象层,
要求开发者一开始就针对抽象层进行设计与编程。 - 要求正确识别出系统中两个独立变化的维度,因此其使用
范围具有一定的局限性,如何正确识别两个独立维度也需要
一定的经验积累。
适用场景
多维变化类或者多个树状图间的耦合;
想为构建的抽象与具体化提供更多灵活性,避免两层次间建立静态的继承联系;
不希望使用继承或因多层继承导致系统类个急剧增加的额系统;
一个类存在两个或多个独立变化的维度,而且都需要独立进行扩展。
本文代码:
https://github.com/coder-pig/DesignPatternsExample/tree/master/9.Bridge%20Pattern