开篇前言
遇一人白首,择一城终老,是多么美好的人生境界,她和他历经风雨慢慢变老,回首走过的点点滴滴,依然清楚的记得当初爱情萌芽的模样,时维十一月,眼看着光棍节就那么轻轻的来了,没有预告,没有准备`(*∩_∩*)′,是否想在双十一摆脱单身,和亲爱的ta牵手漫步,在寒风中紧紧相拥,都说艺术来源于生活,却高于生活,作为人类智慧的结晶设计模式,她蕴藏着丰富的撩妹技术,今天这篇博文,小编主要介绍桥接模式中的撩妹神技。
什么是桥接模式
在软件系统中,某些类型由于自身的逻辑,她具有两个或者多个维度的变化,那么如何应对这种多维度的变化?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而不引入额外的复杂度,于是,桥接模式伴随着第一声的啼哭,来到这个世界`(*∩_∩*)′,桥接模式,将抽象部分与她的实现部分分离,使她们可以独立的变化,我们来看一下桥接模式的结构图:
桥接模式中的撩妹神技
接着,小编就来举一个例子,帮助小伙伴们更好的了解桥接模式以及桥接模式中的撩妹神技,新建项目,项目 名称Bridge,新建类MM,我们给MM一个属性,编写相关的代码部分,如下所示:
package com.dp.bridge; public class MM { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
新建类Boy,也就是追MM的人,编写相关的代码部分,如下所示:
package com.dp.bridge; public class Boy { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
运用面向对象的思维,男孩儿追MM,这个应该怎么样进行封装呢?亲爱的小伙伴们,可以想一想哦,我们可以这样来写,代码如下所示:
package com.dp.bridge; public class Boy { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void pursue(MM mm){ } }
那么追MM的方法有什么呢?送鲜花?送巧克力?牵手?所以我们的代码就可以这样来写,在写追MM的方法之前,我们需要按照面向对象的方法,我们来创建一个类Gift,你送MM一个礼物,不能单一是不是,得要五花八门,层出不穷,千变万化,不能千篇一律,最常见的礼物有什么呢?可以有鲜花,so,我们创建一个鲜花的类:
package com.dp.bridge; public class Flower extends Gift { }
当然,如果你是土豪,还可以送MM钻戒,俘获她的芳心,让她拜倒在你的石榴裙下`(*∩_∩*)′,同样的,我们可以新建一个钻戒类Ring。这个时候,Boy追MM的方法就有很多了,so,我们来编写Boy追MM的方法:
package com.dp.bridge; public class Boy { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void pursue(MM mm){ Gift g = new Ring(); give(g,mm); } public void give(Gift g,MM mm){ } }
不过呢?作为礼物,我们可以从另外一个角度来做区分,如果你要追的是一个温柔的MM,这个时候,你就需要送一个温柔的礼物,我们可以新建一个类WarmGift,如下所示:
package com.dp.bridge; public class WarmGift extends Gift { }
当然啦,如果你追的MM比较狂野,你可以送一个狂野的礼物,让她对你死乞白赖`(*∩_∩*)′,所以我们新建一个WildGift。作为礼物来说,在她往子类发展的时候,他会有两个维度上的扩展,一种是具体的维度,比如说Ring,还有一个种是类型上的划分,比如温柔类型的WormGift,两个维度扩展的时候,他们之间可能会有交叉,小伙伴们看下面这张类图,就明白了`(*∩_∩*)′
她们会有各种各样的排列组合,如此下去,你会发现子类是无穷无尽的。这个时候,我们可以采用桥接模式进行设计,我们需要增加一个新的类,具体的礼物的实现:
package com.dp.bridge; public class GiftImpl { }
让Ring和Flower都继承我们的GiftImpl,这个时候,Gift和GiftImpl之间的关系就会变成聚合,我们可以这样来实现:
package com.dp.bridge; public class Gift { protected GiftImpl impl; }
用聚合代替继承,如果这个时候要送一个温暖的花儿,我们该如何实现呢?如下所示:
package com.dp.bridge; public class WarmGift extends Gift { public WarmGift(GiftImpl impl){ this.impl=impl; } }
当然,如果你想送一个狂野的戒指,可以这样来编写:
package com.dp.bridge; public class WildGift extends Gift { public WildGift(Ring ring){ this.impl = impl; } }
这个时候,如果你想用worm flower,我们可以在Boy中这样写,代码如下所示:
package com.dp.bridge; public class Boy { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void pursue(MM mm){ // Gift g = new Ring(); // give(g,mm); // Gift g = new WarmGift(new Flower()); Gift g = new WildGift(new Ring()); } public void give(Gift g,MM mm){ } }
这样,我们排列组合起来就非常方便了,这就是我们的桥接模式,如果子类的扩展有两个维度,那么这个时候你想解耦合,解决排列组合的问题,我们就可以使用桥接模式。
桥接模式的优缺点
优点:
a、分离抽象和实现部分
桥接模式分离了抽象部分和实现部分,从而极大地提高了系统的灵活性,让抽象部分和实现部分独立开来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统,对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。
b、更好的扩展性
由于桥接模式把抽象部分和实现部分分离开了,而且分别定义接口,就这使得抽象部分和实现部分可以分别独立的扩展,而不会相互影响,从而大大的提高了系统的扩展性。
c、可动态的切换实现
由于桥接模式把抽象部分和实现部分分离开了,所以在实现桥接的时候,就可以使实现动态的选择和使用具体的实现,也就是说一个实现不再是固定的绑定在一个抽象接口上了,可以实现运行期动态的切换。
d、可减少子类的个数
根据前面的讲述,对于两个变化维度的情况,如果采用继承的方式实现,大约需要两个维度上的可变换数量的乘积个子类,而采用桥接模式来实现,可以明显的减少子类的个数。
缺点:
a、桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
b、桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
桥接模式的应用场景
a、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
b、抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
c、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
d、虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
e、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
小编寄语:该博文小编主要介绍了设计模式中的桥接模式,从什么是桥接模式、模式的结构图,桥接模式的demo、桥接模式的应用场景以及她的使用场景,她可是一个撩妹神奇的设计模式哦`(*∩_∩*)′,所以嘛,工作、生活、学习、恋爱都是相互关联的,把学习到的知识用到生活中,用到追MM上,是不是觉得学起来一下子就变得简单轻松和快乐,祝愿小伙伴们赶紧在双十一前脱单,找到你人生中的soul mate,在下篇博文中,小编将继续介绍设计模式中的撩妹神技,敬请期待`(*∩_∩*)′。