First we try, then we trust

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  183 随笔 :: 111 文章 :: 3133 评论 :: 358 引用

我想大家小时候都有用蜡笔画画的经历吧。红红绿绿的蜡笔一大盒,根据想象描绘出格式图样。而毛笔下的国画更是工笔写意,各展风采。而今天我们的故事从蜡笔与毛笔说起。

设想要绘制一幅图画,蓝天、白云、绿树、小鸟,如果画面尺寸很大,那么用蜡笔绘制就会遇到点麻烦。毕竟细细的蜡笔要涂出一片蓝天,是有些麻烦。如果有可能,最好有套大号蜡笔,粗粗的蜡笔很快能涂抹完成。至于色彩吗,最好每种颜色来支粗的,除了蓝天还有绿地呢。这样,如果一套12种颜色的蜡笔,我们需要两套24支,同种颜色的一粗一细。呵呵,画还没画,开始做梦了:要是再有一套中号蜡笔就更好了,这样,不多不少总共36支蜡笔。

 

再看看毛笔这一边,居然如此简陋:一套水彩12色,外加大中小三支毛笔。你可别小瞧这"简陋"的组合,画蓝天用大毛笔,画小鸟用小毛笔,各具特色。

 

呵呵,您是不是已经看出来了,不错,我今天要说的就是Bridge模式。为了一幅画,我们需要准备36支型号不同的蜡笔,而改用毛笔三支就够了,当然还要搭配上12种颜料。通过Bridge模式,我们把乘法运算3×12=36改为了加法运算3+12=15,这一改进可不小。那么我们这里蜡笔和毛笔到底有什么区别呢?

实际上,蜡笔和毛笔的关键一个区别就在于笔和颜色是否能够分离。【GOF95】桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化"。关键就在于能否脱耦。蜡笔的颜色和蜡笔本身是分不开的,所以就造成必须使用36支色彩、大小各异的蜡笔来绘制图画。而毛笔与颜料能够很好的脱耦,各自独立变化,便简化了操作。在这里,抽象层面的概念是:"毛笔用颜料作画",而在实现时,毛笔有大中小三号,颜料有红绿蓝等12种,于是便可出现3×12种组合。每个参与者(毛笔与颜料)都可以在自己的自由度上随意转换。

蜡笔由于无法将笔与颜色分离,造成笔与颜色两个自由度无法单独变化,使得只有创建36种对象才能完成任务。Bridge模式将继承关系转换为组合关系,从而降低了系统间的耦合,减少了代码编写量。但这仅仅是Bridge模式带来的众多好处的一部分,更多层面的内容,请参考《设计模式(16)-Bridge Pattern》。

本文代码附于此处:

using System;

abstract class Brush
{
  
protected Color c;
  
public abstract void Paint();

  
public void SetColor(Color c)
  
this.c = c; }
}


class BigBrush : Brush
{
  
public override void Paint()
  
{ Console.WriteLine("Using big brush and color {0} painting", c.color); }
}


class SmallBrush : Brush
{
  
public override void Paint()
  
{ Console.WriteLine("Using small brush and color {0} painting", c.color); }
}


class Color
{
  
public string color;
}


class Red : Color
{
  
public Red()
  
this.color = "red"; }
}


class Blue : Color
{
  
public Blue()
  
this.color = "blue"; }
}


class Green : Color
{
  
public Green()
  
this.color = "green"; }
}


class Client
{
  
public static void Main()
  
{
    Brush b 
= new BigBrush();
    b.SetColor(
new Red());
    b.Paint();
    b.SetColor(
new Blue());
    b.Paint();
    b.SetColor(
new Green());
    b.Paint();

    b 
= new SmallBrush();
    b.SetColor(
new Red());
    b.Paint();
    b.SetColor(
new Blue());
    b.Paint();
    b.SetColor(
new Green());
    b.Paint();
  }

}
posted on 2004-11-22 14:32 吕震宇 阅读(8919) 评论(49)  编辑 收藏 网摘 所属分类: 设计模式随笔系列

评论

#1楼 2004-11-22 14:55 montaque      
hehe,a simple but meaningful example.
  回复  引用  查看    

#2楼 2004-11-22 15:28 jiangyu
太棒了。
吕大哥,由于我现在的工作基本上都是与数据库打交道,所以有的时候只能屈就于数据库结构。
模式啊,思想挺好,但就是不会用,郁闷。
谢谢您的这些好东西。

  回复  引用    

#3楼 2004-11-22 16:04 Rickie      
Good example.
  回复  引用  查看    

#4楼 2004-11-22 17:43 大漠孤烟      
Good example.
  回复  引用  查看    

#5楼 2004-11-22 21:30 onekey      
通俗易懂,妙就一个字!
  回复  引用  查看    

#6楼 2004-11-23 00:04 小新0574      
不错,写得很好懂,有点国外技术作者的写作风格
  回复  引用  查看    

#7楼 2004-11-26 10:22 wayfarer      
老实说,我看了这篇文章,只有一个字可以表达我的仰慕之情,那就是:震宇兄,你真牛啊!

我还没有把文章看完,就迫不及待地将本文加入到精华区了。是否草率?不,一点也不,只是因为这个比喻实在是太棒了,用毛笔和蜡笔的区别,来描述Bridge模式,真是微妙微肖。根本不用看代码,你会立即体会到这种设计模式给程序设计带来的好处了。

真是好文章啊,佩服!

  回复  引用  查看    

#8楼 2004-11-26 10:45 jeseeqing      
震宇兄你的设计模式系列真的让我受益非浅呀!

在看你的文章的同时,真的很佩服震宇兄你的中文的功底.

希望看到你的更多的好文章!

  回复  引用  查看    

#9楼 2005-01-27 13:05 idior      
交流一下
http://www.cnblogs.com/idior/articles/97283.html">http://www.cnblogs.com/idior/articles/97283.html

  回复  引用  查看    

#10楼 2005-02-20 20:26 lijing2001
太形象了!
  回复  引用    

#11楼 2005-03-30 12:41 Duiker      
很好,真的很喜欢
  回复  引用  查看    

#12楼 2005-04-29 17:49 仁渣
想形容几句,却发现自己没有那个文采,等我去找金庸先
  回复  引用    

#13楼 2005-06-29 09:14 cv222
恩, 不错, 这个范例给的好, 对bridge有个直观印象了, 谢谢吕震宇
  回复  引用    

#14楼 2005-08-29 11:38 neushi[未注册用户]
拜读了您的不少文章,但是好像关于主要23种设计模式还没有写全,不知道什么时候可以见到如Mediator、State等的文章,期待ing...
  回复  引用    

不错!多多益善。

  回复  引用    

woaizhegewenzhang
  回复  引用    

woaini laogong
  回复  引用    

#18楼 2005-11-01 17:51 ls0627[未注册用户]
很形象,谢谢吕大哥了。
  回复  引用    

#19楼 2005-11-05 14:41 asp[未注册用户]
原来bridge模式就是这样的,谢谢~让我受益非浅
  回复  引用    

#20楼 2005-12-20 17:56 汪新厚      
谢谢,大道至简!!!期待吕兄的新作!!
  回复  引用  查看    

#21楼 2006-04-23 21:17 夏林[未注册用户]
爱生活,爱吕哥
  回复  引用    

#22楼 2006-06-28 13:24 隨風.NET      
不去当作家 浪费了
  回复  引用  查看    

#23楼 2006-09-19 11:33 kingmu[未注册用户]
吕兄,你的毛笔和蜡笔的举例有很明显的差别,感觉不错.但个人感觉用它们不足以体现Bridge模式的精髓,因为Bridge pattern的Goal是通过抽象与实现的分离实现各自的变化和灵活的组合,Implement 一般是实现一组操作.Color在此表示implementor,感觉不是很清晰.
  回复  引用    

#24楼 2006-10-12 15:16 轻风[未注册用户]
写的不错,感觉比调治解调器的那个好,可能是因为我才接触设计模式,太复杂的理解不了,谢谢!!学到好多东西!
  回复  引用    

#25楼 2007-01-22 20:12 afuture[未注册用户]
感觉比喻的有点问题。
蜡笔和毛笔中的颜色和大小通过抽象都应该是一个类的属性。呵呵

  回复  引用    

#26楼 2007-04-25 11:24 wangle[未注册用户]
说得太好了
  回复  引用    

#27楼 2007-07-21 20:34 天纯蓝      
通俗易懂.太棒了!!!让我想起了C#中的泛型.可以应用到实际当中.
  回复  引用  查看    

#28楼 2007-08-17 16:21 asong[未注册用户]
这个随笔系列中这一篇是最通俗绝妙的了
  回复  引用    

说的太棒了
  回复  引用    

例子很生动!!!
  回复  引用    

#31楼 2007-11-23 16:29 good[未注册用户]
good
  回复  引用    

写的真好,谢谢你
  回复  引用    

#33楼 2008-01-11 12:07 royi_e[未注册用户]
我最近有这样一个需求,需要做一个工资管理模块.里面有个功能是晋级的.
晋级的条件是动态的,写在数据库里的.比如可能的晋级条件有
1.至2008工作年限满30年,今年自动晋升一档次
2.在同一级别连续干2年,自动晋升一档次
3.在同一职务上干5年,自动提升该职务对应级别的一个级别(比如厅长可能对应4,5,6三个级别,如果是6级,则提升到5级);
....
条件很多,而且可能动态增删的.我想了想,有点象防火墙的控制访问列表.
我最开始想用修饰器模式,后来想了想,这个方式不行.因为晋级条件是动态的,而且数目众多.
我想问的问题是,设计到动态匹配时,采用什么模式好.
---------请大家指点迷津,我就要动手编码了,还是一片茫然.

  回复  引用    

39楼的,明显是个strategy模式
  回复  引用    

#35楼 2008-01-19 22:20 Weck      
例子是简单,可怎么灵活应用到实际编程中去,真的还需要深深体会
  回复  引用  查看    

#36楼 2008-06-06 13:18 Hiken[未注册用户]
吕兄,最近一直在拜读你的设计模式系列,多谢写出这么好的文章,例子很好,很生动...
  回复  引用    

佩服,精彩,多谢分享
  回复  引用    

楼主到07年4月就没再写过东西了
太可惜了。。。
这篇替我解决了一个大问题
太谢谢楼主了,希望有空和楼主交流下!

  回复  引用    

#39楼 2008-12-10 16:13 cxp[未注册用户]
不好意思,能否将再将‘“桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化"。关键就在于能否脱耦”’解释的更清楚些?"二者"何指?如果是指 抽象化&实现化,独立的变化又作何解释?
看完老师的文章,我的理解是桥接模式的用意是将抽象化的概念在实现的过程中降低耦合,“用笔作画”是抽象层次的概念,而蜡笔、毛笔&颜料作画是实现层。相对于蜡笔作画,毛笔&颜料耦合度更小,所以毛笔&颜料模式相对于蜡笔就是一种较好的桥接模式。不知我的理解与老师所想表达的有无出入?

  回复  引用    

#40楼 2009-02-05 15:25 jgg[未注册用户]
太OK啦
  回复  引用    

#41楼 2009-02-06 03:08 Hr      
@kingmu
我觉得不需要非要把color看做成一个动作,模式的应用不局限于它的严格定义,而是理解它的作用,只要能解决很实际的问题即可,我们如果把蜡笔和颜色抽成是笔和着色器是不是就可以看成一个动作了,那么笔只是画的动作而已,而着色器则是将笔经过的路径染成相应的颜色即可,各自在不同的领域里延伸发展,做笔的厂商只管做大笔,中笔,小笔,金属笔等等并给做出的笔都预定好着色器的接口,而做着色器的厂商也不管做笔的厂商生产了什么笔只管按照一定的接口契约来指定着色器的颜色及其着色的方法,用户则根据不同的选择自由搭配,我可以搭配金属黄笔,也可以搭配金属红笔,在2个业务领域里他们分别各自发展.自然在2个方面都解耦了,不知道这么理解是否正确,大家也可以发表自己的意见.

  回复  引用  查看    

--引用--------------------------------------------------
royi_e: 我最近有这样一个需求,需要做一个工资管理模块.里面有个功能是晋级的.
<br>晋级的条件是动态的,写在数据库里的.比如可能的晋级条件有
<br>1.至2008工作年限满30年,今年自动晋升一档次
<br>2.在同一级别连续干2年,自动晋升一档次
<br>3.在同一职务上干5年,自动提升该职务对应级别的一个级别(比如厅长可能对应4,5,6三个级别,如果是6级,则提升到5级);
<br>....
<br>条件很多,而且可能动态增删的.我想了想,有点象防火墙的控制访问列表.
<br>我最开始想用修饰器模式,后来想了想,这个方式不行.因为晋级条件是动态的,而且数目众多.
<br>我想问的问题是,设计到动态匹配时,采用什么模式好.
<br>---------请大家指点迷津,我就要动手编码了,还是一片茫然.
--------------------------------------------------------


我觉得这个问题问得很实际,在工作中很容易遇到这类问题,可惜怎么没有人给与回复呢?

我的解决方案是:对于工资晋级的条件作为可配置的多个comparison后的结果,每一个compariosn都实现同一个接口,接口内可能只有一个用于比较的方法,该方法返回true或者false.
每一个comparision具备的属性包括,comparision的Id,对应的Java类,And或者Or的权限等。
当判断是否晋级时,依次调用每一个comparison,根据各个comparison的And或Or权限得到最终的true或false,从而决定是否晋级

  回复  引用    

赞啊,一直不明白birdge,突然豁然开朗了。
  回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 67016




相关文章:

相关链接: