这一章,她学会了"桥接":两个维度都在变?拆开各管各的,中间架座桥。起因,是她逛淘宝想买一整套水彩笔,被我拦住了。
晚上八点,书桌
她捧着手机:"你看这家水彩笔,型号有大的、中的、小的,颜色有红的、黄的、蓝的------全配齐九支,四十八块钱!"
"你想要多少种搭配?"
"我画画嘛,有时要粗的红,有时要细的蓝......"她数着,"都得有,那不就 3×3=9 支?"
"那你看看这个。"我从抽屉里拿出毛笔和颜料盒,"笔三支:大、中、小;颜料三盒:红、黄、蓝。想画粗的红?粗笔蘸红。想画细的蓝?细笔蘸蓝。3 支笔 + 3 盒颜料,6 样东西,9 种搭配随便画。"
"哦!!"她眼睛亮了,"水彩笔是把颜色焊死在笔上,买齐搭配得花九支的钱;毛笔和颜料是分开的,蘸一下就配上了!"
"对,这就是桥接------两个维度分开管,用的时候'蘸'一下连起来。"
第一步:程序里,别跟水彩笔一样焊死
"程序里也一样。假如你要画形状,有圆有方,每种还得配不同颜色------最笨的办法就是'水彩笔',每种组合写一个类:"
java
class RedCircle { ... }
class BlueCircle { ... }
class RedSquare { ... }
class BlueSquare { ... }
"红圆、蓝方......写四个还行。可再加一种形状三角形?再添一种颜色紫色?"
"那不就......红圆、蓝圆、紫圆、红方、蓝方、紫方......九支'水彩笔'!"
"对,形状 × 颜色,疯狂膨胀,还全是重复代码------你改一下红色,所有带红的类都得跟着动。别焊死,像毛笔那样拆开:"
java
// 维度一:形状,只管画
abstract class Shape {
protected Color color; // 桥:形状里放一个颜色
abstract void draw();
}
// 维度二:颜色,只管填色
interface Color { void fill(); }
class Red implements Color { public void fill() { /* 红色 */ } }
class Blue implements Color { public void fill() { /* 蓝色 */ } }
// 圆,画的时候用桥上的颜色
class Circle extends Shape {
void draw() { /* 画圆 */; color.fill(); }
}
"画圆就画圆,颜色从桥上拿。将来加三角、加紫色,各加一个类就行------红色不拖累形状,加形状不碰颜色。"
"哦------3 支笔画所有搭配,就是因为型号和颜料各管各的,谁都不绑架谁。"
第二步:还有个更贴身的例子
"那这种'拆开',是不是还挺常见的?"她问。
"太常见了。你家墙上的开关------开关是'按钮'还是'拉线',是一回事;对面的电器是电灯还是风扇,是另一回事。"
"然后呢?"
"'按钮开关'能连电灯,也能连风扇;'拉线开关'也一样,谁都能接。"我说,"两种开关 × 两种电器,随便配------但不需要为'按钮电灯''拉线电灯''按钮风扇''拉线风扇'各造一套专有的控制系统。"
"哦!"她指着墙,"开关只管'通不通电',电器只管'通电干活儿'------中间的墙和电线把两边连起来,就完事了。"
"对,这就是桥接的本质:把抽象部分(开关)和实现部分(电器)分离,让它们都能独立变化,用'组合'代替'一层层继承',避免类爆炸。 但也不是啥都拆------只有两个方向都在变、组合会爆炸才值得拆。就一种形状、一种颜色,老老实实写两个类就完了,别折腾桥。"
"......有数了。"
她自己总结了一句
她举着毛笔,说:
"水彩笔把型号和颜色焊死在一支笔上,想画九种搭配得买九支;毛笔和颜料分开,三支笔加三盒颜料,蘸一下就出九种。程序里也一样------两个维度都在变,别写成一堆组合类,拆开各管各的,中间'蘸'一下连起来。但只有一个维度在变,就别硬拆。"
"......全对。"
"嘿嘿。"她放下毛笔,"那这个桥我能用电脑上吗?我电脑里文件好多,一层套一层的......"
"你想问文件夹的事?"
"对呀,文件和文件夹操作起来感觉像一回事。"
"下一章,组合:文件夹里套文件夹,文件和文件夹统一操作。"
附:这一章她学到的,就一句话------两个维度都在变?像毛笔和颜料一样拆开,蘸一下就配上------桥接。
(下一篇:组合------文件夹套文件夹,文件和文件夹一起操作。)