3.2 Bridge(桥接)
桥接模式中的这个起连接作用的“桥”其实是不存在的,至少不是用代码直接写出来的,而是说在这种模式中,抽象和实现之间有一种起到像桥梁一样的连接作用的关系,根据这个特点取名为“桥接模式”。
很多时候我们可能会把实现代码直接写到类里面去,这样一来子类只需要继承父类并扩展自身就可以成为功能更加强大的类,帮助我们完成更多的事情。这一点完全符合面向对象的思维方式,但是请时刻记住,我们面临的“战场”是千变万化的,兵不厌诈,没有太多硬性的规律可循,同样的信息管理系统,两个不同的客户就可能提出完全不同需求。
我们可以假设一个情景来更好地理解桥接模式:我们假设有一个煤炭行业的大型国有企业,因为煤矿工人众多,劳动强度大,所以对工作服的需求也非常大,这家企业便专门成立了一个不算小的服装车间来制作矿工的工作服,这种现象在几乎所有的大型国有企业都非常正常,我想各位应该都不是90后,所以也很容易理解。这个车间专门制作工作服,在设计方面也不是灵活的,矿工的工作服不会一年换一个样式,设计上的变化大多也都是在容易磨损的地方增加布料或者改善制作工艺。如果快过国庆了,工会组织大型文艺晚会,需要一批旗帜、道具、戏服,找服装车间来做很可能不现实,首先服装车间未必能设计和做出戏服来,另外服装车间也未必有时间来做这些东西,所以工会很可能会组织一些会用缝纫机的女工或工人家属,从服装车间借来一些闲置的缝纫机进行赶制。再假设一个场景,由于当地经济的发展,轻工业的进步也突飞猛进,一家做服装设计和生产的小公司接到了一份来自广东的大订单,说大也不大,但需求量比这家公司目前实际生产能力高出一大截,老板自然会感觉有点儿“撑”,但我相信他不会拒绝这份订单的,于是他找到这家国企的服装车间主任,提出想通过外包的方式由服装车间为其制作一部分服装,该公司提供原料和加工费,服装车间出人出工具。显然,这通常也不现实,首先,以矿工工作服和品牌服装在生产工艺上的差异来讲,服装车间显然不具备后者的各种必备工具和技术人员,如果因为这一笔生意就将服装车间进行扩建扩编,很可能入不敷出,另外,国企领导层常有的官僚作风也是不允许某个车间直接跟外界有任何商业往来的,总之,这笔买卖没做成,服装车间还是一如既往地重复地做着单调的工作服,而那位老板不得不另找下家来帮他一起搞定这笔订单。终于,在一河之隔的邻市有一家主要做服装代工的工厂非常愿意一起合作,而且该工厂实力比较大,这笔订单的数量对他们来说就是小菜一碟儿,而且他们甚至还可以同时接其它的订单,于是这家公司就完全可以把精力集中在设计上,而制作则全部交由对岸的那家工厂去就行了,明确的分工再加上各司其职,这笔生意很快就非常出色地完成了。那么我们来分析一下,为什么最近的服装车间不能做而只好交给远一点儿的工厂呢?
首先,服装车间的制作工艺太单一,而且相当死板,他们甚至除了工作服,连业余水平的文艺晚会所需的戏服都做不出来,这种固定的实现方式限制了其自身的发展,因此就算是标准的劳动密集型,也接不到服装代工的订单;另外,服装代工厂是专门从事服装代工的,所谓“术业有专攻”,这正是人家的强项,所以该工厂不可能傻到只代工某一种类型的服装而其它的一律不接,我在前文中也提到,它们的规模和实力甚至可以同时接几个不同需求的订单,用句IT行业的专业术语来说:人家在实现方式上可以实现跨平台。而从这次的订单来看,服装设计公司集中全部精力做服装设计,代工厂则集中精力从事生产,这样就让逻辑和实现分离开来,不会出现像服装车间那种逻辑和实现紧耦合,来了别的订单(逻辑),自身的生产能力(实现)就无用武之地了。为了让“桥接模式”更形象一点儿,所以我们假设那家代工厂在河对岸,跟这家服装设计公司之间通过一座桥梁来连接。而这两家企业实体之间的联系也就是这座“桥”,所以耦合度是很低的,两家企业可以分别发生很多变化而不会影响对方,例如设计公司可以增加设计工作室,招聘新设计师,而工厂则不需要相应作出任何变化;工厂可以调换车间主任,或者增加新型的设备而不需要设计公司做出任何相应调整。这种模式在需要将逻辑和实现进行分离的时候非常实用。
最后我们还是看代码来说话吧:
1: using System;
2:
3: namespace Autumoon.DesignPatterns.Bridge
4: {
5: public class ClothesFactory
6: {
7: public virtual void MakeClothes(string styleName)
8: {
9: Console.WriteLine("All clothes are made by departments.");
10: }
11: }
12:
13: public class ClothWorkshop : ClothesFactory
14: {
15: public override void MakeClothes(string styleName)
16: {
17: Console.WriteLine("This workshop makes {0} style clothes.", styleName);
18: }
19: }
20:
21: public class TrousersWorkshop : ClothesFactory
22: {
23: public override void MakeClothes(string styleName)
24: {
25: Console.WriteLine("This workshop makes {0} style trousers.", styleName);
26: }
27: }
28:
29: public class DesignCompany
30: {
31: public ClothesFactory MakeClothes { get; set; }
32:
33: public virtual void DesignClothes(string styleName)
34: {
35: this.MakeClothes.MakeClothes(styleName);
36: }
37: }
38:
39: public class DesignStudio : DesignCompany
40: {
41: public override void DesignClothes(string styleName)
42: {
43: base.MakeClothes.MakeClothes(styleName);
44: }
45: }
46:
47: public class BridgeDemo
48: {
49: public DesignCompany Implementation()
50: {
51: DesignCompany designer = new DesignStudio();
52: designer.MakeClothes = new TrousersWorkshop();
53:
54: return designer;
55: }
56: }
57: }
接下来我们来使用这段代码:
1: static void Main(string[] args)
2: {
3: #region Bridge
4: DesignCompany designer = new BridgeDemo().Implementation();
5: designer.DesignClothes("Franch");
6: #endregion
7:
8: Console.ReadLine();
9: }
这次说得有点儿多,有点儿违背“简明设计模式”的初衷,下次一定改进,希望没有误导你!