Internet Explorer 6.0IEVisual C++ 7.0Visual Studio .NET 2003.NET 1.1Windows XPBeginnerHTMLDevVisual StudioWindowsC++.NETC#
软件设计模式(简化版)- 抽象工厂 - 第 1 部分






3.22/5 (31投票s)
2005年8月25日
6分钟阅读

37546
又名 (D博士和他的软件设计历险记)
引言
什么是工厂?一个生产产品的地方……好吧,这个定义不是来自牛津词典……无论如何,让我们想象你是一个失散多年的大亨之子,你从父亲那里继承了一亿美元。现在你就是新的大亨了。酷。但猜猜看,你不能享受所有这些钱……你必须实现你父亲的遗愿,建造一个汽车工厂。一个能让亨利·福特工厂黯然失色的工厂。两天后,你从震惊中恢复过来,打电话请D博士到你家征求他的建议。(D博士代表设计博士 :-))
你还给你的(吞钱的)市场分析师打了个电话,他会就汽车的最新潮流和趋势给出建议。他解释说,在汽车方面,公众分为两类……一类是“跑车”,富有的年轻人会开着它带他们的女孩去赌场兜风;另一类是“家用车”,(可悲的)“一家之主”必须开着它带家人去最近的杂货店为家人下一顿饭采购谷物和蔬菜。唉。
无论如何……你就是大亨……你把要求告诉了D博士。(告诉你,D博士是个典型的书呆子,鼻子上架着三副眼镜,喜欢和一群诺贝尔物理学奖得主共进午餐,讨论爱因斯坦在计算相对论时犯的错误。)
(对话)
(对话)
大亨: “嘿,D博士……听着。我想建一个生产两种汽车(家用型和跑车型)的工厂。我不管你怎么做,但当我命令生产一批‘家用车’时……我希望每天有10辆停在发货区外面……当我想要‘跑车’时……它们应该很快就能准备好。一切都取决于市场条件,但我应该有完全的控制权,可以随时切换生产任何类型的汽车并使用它(比如试驾什么的)。”
D博士 : “嗯,好吧,所以你想要一个非常灵活的环境,你订购哪种类型的汽车……瞧,它就停在停车场里。所以你不用担心汽车内部是什么,以及制造汽车时生产了哪些产品。”
大亨: “你说得对,伙计。无论如何……我想知道你一周内会做什么,否则你可以在工地度过你的午餐时间。回头见。”
于是我们可怜的D博士回家了……不理会他的妻子……(让我想起《美丽心灵》:-))径直走向他的“模式室”。
D博士 : “嗯,好吧,现在,每辆汽车都需要什么才能达到车辆状态。让我记下来。”
模式室 (绘图板)
1. 车架
2. 汽车内饰
3. 汽车配件
1. 车架
2. 汽车内饰
3. 汽车配件
D博士 : “我把这个工厂叫做‘CarFactoryX’。这个工厂是未来汽车工厂的蓝图。嘿,既然我有了蓝图,让我来绘制专业工厂……‘CarFactoryFamily’和‘CarFactorySports’。”
模式室 (绘图板)

D博士 : “现在,我需要深入了解。每个单独的产品,例如车架,可能会根据每种车型而变化。‘跑车’将有‘流线型车架’,‘家用车’将有‘厢式车架’。汽车内饰和汽车配件也必须这样做。”
模式室 (绘图板)

D博士 : “很好,我正在取得进展。我必须将相应的工厂连接到各个产品。为了更好地理解。‘CarFactoryFamily’中的方法知道它想要生产哪种‘CarFrame’、‘CarInteriors’和‘CarAccessories’。因此,自然而然地,在以下情况下:
“家用车”
> “Create_Car_Frame()”使用或实现“CarFrameBox”(对象)。
> “Create_Car_Interiors()”使用或实现“CarInteriorsPlain”(对象)。
> “Create_Car_Accessories()”使用或实现“CarAccessoriesCD”(对象)。
> “Create_Car_Interiors()”使用或实现“CarInteriorsPlain”(对象)。
> “Create_Car_Accessories()”使用或实现“CarAccessoriesCD”(对象)。
同样地
“跑车”
> “Create_Car_Frame()”使用或实现“CarFrameSleek”(对象)。
> “Create_Car_Interiors()”使用或实现“CarInteriorsRoyale”(对象)。
> “Create_Car_Accessories()”使用或实现“CarAccessoriesDVD”(对象)。
> “Create_Car_Interiors()”使用或实现“CarInteriorsRoyale”(对象)。
> “Create_Car_Accessories()”使用或实现“CarAccessoriesDVD”(对象)。
模式室 (绘图板)

D博士解释道: “好的各位,为了让你们了解技术术语,后缀为‘X’的类都是‘抽象类’,也就是说,它们充当其他非‘X’类的蓝图。这些是‘具体’产品。简单来说,你不能有一个名为‘CarFrameX’的产品。这是蓝图或‘抽象产品’。但你肯定可以有一个‘CarFrameSleek’,这是实现‘抽象产品’的‘具体产品’。”
所以你拥有的是一堆抽象(蓝图)和具体(实现)
抽象工厂 (CarFactoryX)
及其相关的
具体工厂 (CarFactoryFamily 和 CarFactorySports)
及其相关的
具体工厂 (CarFactoryFamily 和 CarFactorySports)
抽象产品 (CarFrameX, CarInteriorsX 和 CarAccessoriesX)
及其相关的
具体产品 (CarFrameBox 和 CarFrameSleek, CarInteriorsPlain 和 CarInteriorsRoyale, CarAccessoriesCD 和 CarAccessoriesDVD)
及其相关的
具体产品 (CarFrameBox 和 CarFrameSleek, CarInteriorsPlain 和 CarInteriorsRoyale, CarAccessoriesCD 和 CarAccessoriesDVD)
更进一步,你的老板(客户端)必须能够访问蓝图(或使用这些蓝图),也就是
抽象工厂 (CarFactoryX)
抽象产品 (CarFrameX, CarInteriorsX 和 CarAccessoriesX)
抽象产品 (CarFrameX, CarInteriorsX 和 CarAccessoriesX)
现在他为什么要使用蓝图,而不是具体的呢?
因为,他可以无缝地完成工作。假设大亨有一个按钮可以随意切换“跑车”和“家用车”的生产,他可以轻松做到,而无需额外的麻烦。由于两种类型的汽车都实现了(或知道)CarFactoryX,任何类型的工厂都可以替换CarFactoryX接口来制造所需的汽车。
让我带你浏览一下主代码,以便感受一下。我不会立即深入内部实现。
Line1: // 创建并试驾家用车
Line2: CarFactoryX family = new CarFactoryFamily();
Line3: ClientTycoonCar bossTest = new ClientTycoonCar ( family );
Line4: bossTest.TakeItForARide();
Line5: // 创建并试驾跑车
Line6: CarFactoryX sports = new CarFactorySports();
Line7: bossTest = new ClientTycoonCar ( sports );
Line8: bossTest.TakeItForARide();
Line2: CarFactoryX family = new CarFactoryFamily();
Line3: ClientTycoonCar bossTest = new ClientTycoonCar ( family );
Line4: bossTest.TakeItForARide();
Line5: // 创建并试驾跑车
Line6: CarFactoryX sports = new CarFactorySports();
Line7: bossTest = new ClientTycoonCar ( sports );
Line8: bossTest.TakeItForARide();
这里“ClientTycoonCar”是客户端。客户端只需要知道这些(大亨的小脑袋里是这样想的)
> 给我造一辆“家用车” (第2行)
> 我想用“家用车” (第3行)
> 开着“家用车”去试驾 (第4行)
> 我想用“家用车” (第3行)
> 开着“家用车”去试驾 (第4行)
> 这次给我造一辆“跑车”……呵呵 :-) (第5行)
> 我想用“跑车” (第6行)
> 开着“跑车”去试驾 (第7行)
> 我想用“跑车” (第6行)
> 开着“跑车”去试驾 (第7行)
……第二天在大亨家
大亨:“嘿,D博士……你有没有给我出什么主意啊。”
D博士 : “当然,看看这个设计。”
大亨:“看起来不错,我们什么时候开始编码。”
D博士 : “哇,你懂编码吗?我以为像你这样的大人物永远不会……”
大亨:“废话连篇……我开玩笑的,医生……你才是要编码的人。所以明天一大早就开始,否则我建议你在出门的时候看看报纸上的招聘广告……好了,好好享受夜晚吧……明天见。再见。”
D博士 : “天哪,谢谢,但今天的薪水呢……”
(门在医生面前砰地一声关上)
D博士 : “……水。”
:-)