Builder生成器模式
这次来学习另一个创建型设计模式:Builder生成器模式。
GOF对Builder模式的定义(1)意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
(2)适用性
1. 当 创建复杂对象的算法 应该 独立于该对象的组成部分以及他们的装配方式 ;
2. 当构造过程必须允许 构造的对象有不同的表示 ;
(3)结构
(4)参与者
Builder:为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder:1. 实现Builder的接口以构造和装配该产品的各个部件
2. 定义并明确它所创建的表示
3. 提供一个检索产品的接口
Director:构造一个使用Builder接口的对象
Product:1.表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程
2.包含定义组成部件的类,包括将这些部件装配成最终产品的接口
(5)协作
下面序列图说明了Builder和Director是如何与一个客户协作的
代码示例
(1)示例简述
前段时间看了电影《超级战舰》,还不错,所以在举例子的时候就想到用builder模式构建一艘船。注意是“船”,我没说构建“战舰”,船的范围就大了,比如有:航母、驱逐舰、潜艇,当然也包括补给船等后勤船只。而不同的船构造也不同,航母上首先有小飞机,玩过星际的人都知道,还有许多电子设备和一些防空武器;驱逐舰上有鱼雷、导弹、防空炮等等。可以说船的构造还是相对比较复杂的。
那么今天的目的就是: 运用builder模式来造一艘“船”。
回忆下Gof对builder模式的描述:“ 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 ”。有这么几个关键点:1. 对象比较复杂,内部可能包含多个元素或者多个其他对象的组合。2. 对象的表示可能有多种,并且有需求在多种表示中进行切换。3.使用同样的构造过程来创建可能的不同表示。
这样看来,“造一艘船”这个事件中,复杂对象指的是不同种类“船”,“船”的内部可能包括其他对象:“鱼雷”、“飞机”等;“船”有多种表示;相同的构建过程则是描述“造船”这个事件的抽象过程,隐藏具体的构造细节,这样才能通过相同的构造过程得到不同的“船”的表示。
(2)示例说明
首先需要定义下船只的构造规则,方便示例的说明,如下:
航母(AircraftCarrier) = n * 飞机(Aircraft) + n * 防空炮(FlakCannon) + 船体(Hull) + n * 设备(Equipment);
驱逐舰(Destroyer) = n * 鱼雷(Torpedo) + n * 防空炮(FlakCannon) + n * 导弹(Missile) + 船体(Hull) + n * 设备(Equipment);
补给船(Tender) = 船体(Hull) + n * 设备(Equipment);
为什么都是n呢?当然是因为不止一个了!
其实这点非常重要!!!在前面结构图中关于导向器(Director)的描述是这样的:
1: for all objects in structure {
2: builder -> buildPart();
3: }
注意这个for,为什么不直接是buildPart()调用,而要循环调用呢?我个人的理解是这样的,每 一类 对象会有一个具体的生成器(ConcreteBuilder)来构造,新增 一类 对象时,也需要新增一个具体的生成器(ConcreteBuilder)。那么对于对象的 类别 应该是根据构造结构来分,而不是根据构造结构的不同数量来分,例如五架飞机的航母和十架飞机的航母构造应该是由同一个具体的航母生成器来完成,而不需要新建另一个具体的生成器。组件数量不同的构造过程应该是在导向器(Director)中根据不同的构造算法来实现的。
为什么会特别关注这个细节,是因为看的一些书和资料有的忽略了这点,代码例子看起来很漂亮,但是细细一想由于数量不同带来的大量新建具体生成器的问题就出来了,我想这显然不是GOF的本意。这里有篇文章写的很好 点击 。
再来看下结构图:
(3)示例代码
废话了这么多该贴代码了:
先是船的一些组件代码,加了很简单的打印。
1: /**
2: * <飞机>
3: */
4: public class Aircraft
5: {
6: public Aircraft( int no)
7: {
8: System.out.println( "生产了编号为" + no + "的战斗机" );
9: }
10: }
1: /**
2: * <各种设备>
3: */
4: public class Equipment
5: {
6: public Equipment( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的设备" );
9: }
10: }
1: /**
2: * <防空炮>
3: */
4: public class FlakCannon
5: {
6: public FlakCannon( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的防空炮" );
9: }
10: }
1: /**
2: * <船体>
3: */
4: public class Hull
5: {
6: public Hull()
7: {
8: System.out.println( "制造了主船体" );
9: }
10: }
1: /**
2: * <导弹>
3: */
4: public class Missile
5: {
6: public Missile( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的导弹" );
9: }
10: }
1: /**
2: * <鱼雷>
3: */
4: public class Torpedo
5: {
6: public Torpedo( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的鱼雷" );
9: }
10: }
再来看下船的代码,具体表示为:航母、驱逐舰、补给船:
1: /**
2: * <航母对象>
3: */
4: public class AircraftCarrier
5: {
6: //航母名称
7: private String name;
8:
9: //舰载飞机
10: private List<Aircraft> aircrafts;
11:
12: //防空炮
13: private List<FlakCannon> flakCannons;
14:
15: //船体
16: private Hull hull;
17:
18: //设备
19: private List<Equipment> equipments;
20:
21: public AircraftCarrier(String name)
22: {
23: this .name = name;
24: equipments = new ArrayList<Equipment>();
25: aircrafts = new ArrayList<Aircraft>();
26: flakCannons = new ArrayList<FlakCannon>();
27: }
28: //get/set方法忽略
29: }
1: /**
2: * <驱逐舰对象>
3: */
4: public class Destroyer
5: {
6: //驱逐舰编号
7: private String name;
8:
9: //防空炮
10: private List<FlakCannon> flakCannons;
11:
12: //船体
13: private Hull hull;
14:
15: //设备
16: private List<Equipment> equipments;
17:
18: //鱼雷
19: private List<Torpedo> torpedos;
20:
21: //导弹
22: private List<Missile> missiles;
23:
24: public Destroyer(String name)
25: {
26: this .name = name;
27: equipments = new ArrayList<Equipment>();
28: flakCannons = new ArrayList<FlakCannon>();
29: torpedos = new ArrayList<Torpedo>();
30: missiles = new ArrayList<Missile>();
31: }
32: //get/set方法省略
33: }
1: /**
2: * <补给船>
3: */
4: public class Tender
5: {
6: //补给船名称
7: private String name;
8:
9: //船体
10: private Hull hull;
11:
12: //设备
13: private List<Equipment> equipments;
14:
15: public Tender(String name)
16: {
17: this .name = name;
18: equipments = new ArrayList<Equipment>();
19: }
20:
21: //get/set方法省略
22: }
下面是生成器(Builder)的代码:
1: /**
2: * <舰船Builder>
3: */
4: public abstract class ShipBuilder
5: {
6: //建造船
7: public abstract void buildShip(String name);
8:
9: //建造船体
10: public abstract void buildHull();
11:
12: //建造设备
13: public abstract void buildEquipment( int no);
14:
15: //建造导弹
16: public abstract void buildMissile( int no);
17:
18: //建造鱼雷
19: public abstract void buildTorpedo( int no);
20:
21: //建造飞机
22: public abstract void buildAircraft( int no);
23:
24: //建造防空炮
25: public abstract void buildFlakCannon( int no);
26:
27: //返回结果
28: public abstract Object getResult();
29: }
生成器可以是抽象类也可以是接口,再来看下几个具体生成器的代码(ConcreteBuilder):
1: /**
2: * <建造航母类>
3: */
4: public class AircraftCarrierBuilder extends ShipBuilder
5: {
6: private AircraftCarrier aircraftCarrier;
7:
8: public void buildShip(String name)
9: {
10: this .aircraftCarrier = new AircraftCarrier(name);
11: }
12:
13: public AircraftCarrier getResult()
14: {
15: System.out.println( "\"" + aircraftCarrier.getName() + "\"号航母制造完成" );
16: return aircraftCarrier;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22: this .aircraftCarrier.getAircrafts().add( new Aircraft(no));
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .aircraftCarrier.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .aircraftCarrier.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .aircraftCarrier.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
1: /**
2: * <驱逐舰建造>
3: */
4: public class DestoryerBuilder extends ShipBuilder
5: {
6: private Destroyer destroyer;
7:
8: public void buildShip(String name)
9: {
10: this .destroyer = new Destroyer(name);
11: }
12:
13: public Destroyer getResult()
14: {
15: System.out.println( "\"" + destroyer.getName() + "\"号驱逐舰制造完成" );
16: return destroyer;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .destroyer.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .destroyer.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .destroyer.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46: this .destroyer.getMissiles().add( new Missile(no));
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52: this .destroyer.getTorpedos().add( new Torpedo(no));
53: }
54: }
1: /**
2: * <补给船建造类>
3: */
4: public class TenderBuilder extends ShipBuilder
5: {
6: private Tender tender;
7:
8: public void buildShip(String name)
9: {
10: this .tender = new Tender(name);
11: }
12:
13: public Tender getResult()
14: {
15: System.out.println( "\"" + tender.getName() + "\"号补给船制造完成" );
16: return tender;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .tender.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34:
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .tender.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
大家也许注意到了,3个具体生成器中存在空方法,比如在航母生成器中的buildMissile和buildTorpedo,因为我们定义的在航母上没有导弹和鱼雷。
GOF在设计模式中举的例子是用C写的,生成器父类里使用了虚函数,有点像java的abstract,在具体生成器子类中可以选择性的重写父类方法,但是java中没有虚函数,所以只能采用接口或者抽象类,那么在子类中必须实现所有的方法,所以我只能给空的实现了。
再来看一下导向器的代码,在导向器中要对Builder进行配置,并如前面结构图中所画的,在导向器中定义了各种构造的算法:
1: /**
2: * Director
4: */
5: public class ShipFactory
6: {
7: private ShipBuilder shipBuilder;
8:
9: public ShipFactory(ShipBuilder shipBuilder)
10: {
11: this .shipBuilder = shipBuilder;
12: }
13:
14: public void createShip( int shipType, String name)
15: {
16: shipBuilder.buildShip(name);
17: shipBuilder.buildHull();
18: switch (shipType)
19: {
20: //中国航母
21: case 1:
22: buildAircraftCarrierCHN();
23: break ;
24: //外国航母
25: case 2:
26: buildAircraftCarrierUSA();
27: break ;
28: //驱逐舰
29: case 3:
30: buildDrstroyer();
31: break ;
32: //补给船
33: case 4:
34: buildTender();
35: break ;
36: }
37: }
38:
39: private void buildAircraftCarrierCHN()
40: {
41: for ( int i=1; i<6; i++)
42: {
43: shipBuilder.buildEquipment(i);
44: }
45: for ( int i=1; i<11; i++)
46: {
47: shipBuilder.buildAircraft(i);
48: }
49: for ( int i=1; i<11; i++)
50: {
51: shipBuilder.buildFlakCannon(i);
52: }
53: }
54:
55: private void buildAircraftCarrierUSA()
56: {
57: for ( int i=1; i<7; i++)
58: {
59: shipBuilder.buildEquipment(i);
60: }
61: for ( int i=1; i<12; i++)
62: {
63: shipBuilder.buildAircraft(i);
64: }
65: for ( int i=1; i<12; i++)
66: {
67: shipBuilder.buildFlakCannon(i);
68: }
69: }
70:
71: private void buildTender()
72: {
73: for ( int i=1; i<6; i++)
74: {
75: shipBuilder.buildEquipment(i);
76: }
77: }
78:
79: private void buildDrstroyer()
80: {
81: for ( int i=1; i<6; i++)
82: {
83: shipBuilder.buildEquipment(i);
84: }
85: for ( int i=1; i<12; i++)
86: {
87: shipBuilder.buildMissile(i);
88: }
89: for ( int i=1; i<12; i++)
90: {
91: shipBuilder.buildFlakCannon(i);
92: }
93: for ( int i=1; i<12; i++)
94: {
95: shipBuilder.buildTorpedo(i);
96: }
97: }
98: }
最后看下使用的代码:
1: public class Client
2: {
3: public static void main(String[] args)
4: {
5: ShipBuilder builder = new AircraftCarrierBuilder();
6: // ShipBuilder builder = new DestoryerBuilder();
7: // ShipBuilder builder = new TenderBuilder();
8: ShipFactory factory = new ShipFactory(builder);
9: factory.createShip(1, "和谐" );
10: // factory.createShip(2, "圣母玛利亚");
11: // factory.createShip(3, "牛逼号");
12: // factory.createShip(4, "龙套号");
13: builder.getResult();
14: }
15: }
运行结果:
1: 制造了主船体
2: 制造了编号为1的设备
3: 制造了编号为2的设备
4: 制造了编号为3的设备
5: 制造了编号为4的设备
6: 制造了编号为5的设备
7: 生产了编号为1的战斗机
8: 生产了编号为2的战斗机
9: 生产了编号为3的战斗机
10: 生产了编号为4的战斗机
11: 生产了编号为5的战斗机
12: 生产了编号为6的战斗机
13: 生产了编号为7的战斗机
14: 生产了编号为8的战斗机
15: 生产了编号为9的战斗机
16: 生产了编号为10的战斗机
17: 制造了编号为1的防空炮
18: 制造了编号为2的防空炮
19: 制造了编号为3的防空炮
20: 制造了编号为4的防空炮
21: 制造了编号为5的防空炮
22: 制造了编号为6的防空炮
23: 制造了编号为7的防空炮
24: 制造了编号为8的防空炮
25: 制造了编号为9的防空炮
26: 制造了编号为10的防空炮
27: "和谐" 号航母制造完成
至此代码示例就结束了。
一些思考
(1)产品(Product)需不需要抽象类?
GOF给出了答案: 通常情况下,由具体生成器生成的产品,它们的表示相差是如此之大以至于给不同的产品以公共父类没有太大意思。
上面船的例子可能不太贴切,毕竟船之间会有公共的东西,但是换个其他的例子比如构造一副画,不同的画之间很难有共同之处,所以给它们公共接口是没有意义的,它们也不需要这样的接口。因为客户通常用合适的具体生成器来配置导向器,客户的位置使得它很容易的就知道Builder的哪个具体子类被使用和能相应的处理它的产品
(2)多重Builder?
在写上面的例子的时候我是颇有些疑问的,船是由船体、设备、武器等构造出来的,而船体、设备、武器等也是由其他级别更低的组件构造的,它们之间也存在着复杂的构造关系。这中间可能有好几层,知道追溯到螺丝、螺母这样的原子级零件,每一层复杂的构造关系都可以用Builder模式表示。而往上,多艘船可以构造成一个舰队;多个舰队构造成海军等等。
于是我陷入了疑惑,这样多层的Builder模式我该如何表示?直到我看到了一句话: Composite模式通常是由Builder生成的 。原来这样多重的Builder关系已经属于另外一种模式了,那么就论Builder模式的话,我们只需要关注其中的一层构造过程就可以了。
关于Builder模式就这么多了,虽然这个模式好像并不经常用。自己理解了Builder模式有一段时间,自觉理解的并不透彻,有些地方还是生搬硬套,也没有实际运用的场景和经验,有一些思考,有一些疑问,希望大家补全,互相学习。
我只是走在路上,偶尔驻足观赏,偶尔回头看看。
分类: 设计模式 , Java相关
http://www.cnblogs.com/tjcjxy/archive/2010/10/31/1865626.html
12 2010 档案
代理模式
摘要: 一、完成者信息:姓名:杨郅昱学号:07770121二、模式信息模式名称:代理模式生活场景:判定是否是三角形然后求出面积:任意给定三个数,先判断是否能构成三角形 如果能构成三角形,在求出三角形的面积。1.不假思索的思路:通过类继承的方式来做上面的例子。即:任意给定三个数字, 用一个类继承运算接口,先判定能否构成三角形,如果能,求出面积;如果不能,则停止运行。2.类结构图:代码浏览:代码1. 存在问题:1. 当调入大量信息时会发费很长时间。2. 进行判定和计算都在一个类中进行,需要大量的时间。3. 如果判定规则变动,则需要大量的修改。2.归纳阶段归纳步骤一当前目标:实现通过一个代理来处理请求,并将 阅读全文
posted @ 2010-12-16 15:15 天津城建学院软件工程 阅读(46) | 评论 (0) 编辑
桥接模式
摘要: 姓名:陈阳学号:07770114一、模式信息模式名称:桥接模式生活场景:考虑一个售楼小区不同的建筑面积、不同楼层的每平米造价成本是不同的。同一建筑面积的屋子,有楼层的高低之分。而同一楼层也会有建筑面积不一样的屋子终极目标:实现适应于扩充到对各种建筑面积的屋子和各种楼层进行建模的情形。1.不假思索的思路:通过类继承的方式来做上面的例子。即:先建立楼层类;然后派生出高楼层类、矮楼层类;然后再高楼层类和矮楼层类上分别派生出:大面积房屋类和小面积房屋类。类结构图:代码浏览:代码存在问题:1.它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有 阅读全文
posted @ 2010-12-15 17:12 天津城建学院软件工程 阅读(20) | 评论 (0) 编辑
迭代器模式
摘要: 一、完成者信息:姓名: 王延学号:07770125二、模式信息模式名称:迭代器生活场景:将保险柜里的钱分类,从中选出假币。终极目标:合计最终真币的总数。 1.不假思索的思路:通过类和类之间参数的调用来实现最后结果。类结构图:代码浏览:代码:存在问题:1.计算过程过于复杂。2.类Real的实用性很差,可以直接去掉。3.继承和调用的次数过多,容易混乱。4.new的对象名过多,容易混搅。2.归纳阶段归纳步骤一、二、四当前目标:实现假币的计算和最后的总和思路:类结构图:代码浏览:代码:设计体会:节省了很多不必要的步骤,是过程简明了很多。减少了出错的可能性,是程序的耦合程度大大减少。 验证结论:用户使用 阅读全文
posted @ 2010-12-15 16:46 天津城建学院软件工程 阅读(16) | 评论 (0) 编辑
享元模式
摘要: 一、完成者信息:姓名:王智超学号:07770120二、模式信息模式名称:享元模式生活场景:考虑生产汽车的场景:一个品牌有各种型号的汽车,每种型号的汽车有相同的参数(如型号,长,宽,高),也有不同的参数(如颜色,马力) ,就可以把相同的参数拿出来共享。终极目标:实现适应于扩充到对各种汽车和各种型号进行建模的情形。1.不假思索的思路:通过给属性赋值的方法来做:没一辆车都有自己的所有的参数的属性。 类结构图: 代码浏览:代码实现:客户端调用: 存在问题: 1.重复代码会很多,相同的型号汽车有一部分参数是相同的; 2.类的结构过于复杂,难于维护; 3.最致命的一点是效率太差。生产大量汽车会创 阅读全文
posted @ 2010-12-15 16:18 天津城建学院软件工程 阅读(41) | 评论 (0) 编辑
装饰模式
摘要: 一、完成者信息:姓名:张璐璐学号:07770232二、模式信息模式名称:装饰模式生活场景:加工蛋糕的场景:现有烤好的蛋糕,接下来我们要给蛋糕切好形状,然后涂上奶油或巧克力,再放上草莓,最后插上蜡烛。1.不假思索的思路: 按类继承的作法如下:类图:代码存在问题:由此可见,如果用类继承实现,子类会爆炸式地增长。动机(Motivate):上述描述的问题根源在于我们“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态物质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能组合)会导致更多子类的膨胀(多继承)。2.归纳阶段如何使“对象功能的扩展”能够根据 阅读全文
posted @ 2010-12-15 15:45 天津城建学院软件工程 阅读(38) | 评论 (1) 编辑
模板方法模式
摘要: 一、完成者信息姓名:陈绯学号:07770230二、模式信息模式名称:模板方法模式1.问题描述生活场景:大家都经常会用到对数据库中表进行操作,有时候数据库中有若干个表,我们往往是一个一个的对相应的表进行连接数据库,然后对指定的表进行增、删、改、查的一系列操作,组后关闭数据库的连接。但是当我们要对大型的数据库进行这些操作的时候,你会发现这些操作很繁琐,要对每一个表都进行相同的处理,加大的数据的操作工作。设计目的:实现对若干个不相同的表进行重复的增删改查工作。2.不假思索的思路思路描述:对TemplateMethod数据库中的Categories表进行数据库的连接,表的增删改查以及数据库的关闭等操作 阅读全文
posted @ 2010-12-09 16:52 天津城建学院软件工程 阅读(325) | 评论 (0) 编辑
访问者模式
摘要: 一、完成者信息:姓名:王璐学号:07770231二、模式信息模式名称:访问者模式生活场景:假如以前食堂的食品和饮料一直都是一个价位,没有变动。这学期开学,由于工商局调节价位,导致普遍商品都涨价了,所以学校食堂里,菜价和饮料都涨价了。终极目标:实现能够对所有的情况进行访问,通知发生变化。不使用访问者模式不假思索的思路:我们去吃饭,首先看菜单,来选择食物,用现在的菜单跟以前的菜单相对比,价位之间的变化。类结构图:代码实现:代码运行结果:存在问题:在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的改变,将会给子类带来很繁重的变更负担,甚至破坏原有 阅读全文
posted @ 2010-12-09 13:07 天津城建学院软件工程 阅读(135) | 评论 (0) 编辑
装饰模式
摘要: 姓名:高振松学号:077701161、生活场景:看过美国科幻片的同学应该都会为美国人那惊人的想象力说折服吧。在美国的科幻片里有一种东西会经常在镜头里出现,那就是会飞行的交通工具(汽车,卡车之类的)。这些交通工具既可以在陆地上跑,也可以在天空中飞行或者在水中行驶。现假设,现在有一家汽车生产商,最近突破一项关键技术,使得所有类型的车辆都可以在天空中飞或者在水中行驶的功能。而你正好在给该生产商开发系统软... 阅读全文
posted @ 2010-12-01 21:49 天津城建学院软件工程 阅读(155) | 评论 (0) 编辑
代理模式
摘要: 姓名:宁前程学号:07770118模式名称:代理模式1.问题描述生活场景:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买,不但买不到自己想要的衣服,还白白的跑了一趟。设计目的:让用户不必非要跑到李宁公司总部去购买。2.不假思索的思路思路描述:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买。类结构图:缺点:这样的设计,为公司造成很多麻烦,也为自己造成很多麻烦。代码:首先定义一个能产生... 阅读全文
posted @ 2010-12-01 21:28 天津城建学院软件工程 阅读(45) | 评论 (0) 编辑
11 2010 档案
闲谈责任链模式
摘要: 责任链模式是使用多个对象处理用户请求的成熟模式,责任链模式的关键是将用户的请求分派给许多对象,这些对象被组织成一个责任链,即每个对象含有后继对象的引用,并要求责任链上的每个对象,如果能处理用户的请求,就做出处理,不再将用户的请求传递给责任链上的下一个对象,如果不能处理用户的请求,就必须将用户的请求传递给责任链上的下一个对象。 阅读全文
posted @ 2010-11-30 23:59 天津城建学院软件工程 阅读(183) | 评论 (0) 编辑
生产器模式
摘要: 作者:苏石 07770107模式名称生产器模式模式介绍生成器(Builder)模式,也被称为建造者模式或构造器模式,属于创建型模式,它是将一个复杂的对象的构造与这个复杂对象的表示分离开 ,使得同样的构建构成可以创建不同的表示。问题提出生活场景:仍以生产洗发水为例,原生产的洗发水只有一种类型,比如:功效是去屑,包装都是一样的。但随着科技的发展、消费水平的提升,只生产这种单一类型的洗发水已经不能满足当... 阅读全文
posted @ 2010-11-30 17:02 天津城建学院软件工程 阅读(116) | 评论 (0) 编辑
Template Method Pattern 模版方法模式
摘要: Template MethodPattern作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的模版方法模式。 问题:现在有一家汽车生产商需要一个管理汽车生产的管理软件。其中在该系统中有一个管理组装汽车的子模块。该模块要能根据不同的汽车类型来组装相应的汽车。汽车的被组装部分分别是汽车的车盖,车地盘,后备箱,车胎。现在来试着实现下该过程。 根据上面的描述,我在这里选择里... 阅读全文
posted @ 2010-11-28 16:15 天津城建学院软件工程 阅读(240) | 评论 (2) 编辑
生成器模式(又名建造者模式、Builder Pattern)
摘要: 姓名:谭鹏飞学号:07770106模式名称:生成器模式1.问题描述生活场景:你玩过种地、种花等类似的游戏吗?这是最近很流行的游戏哟!下面就是从种花游戏中剪切的四个花盆(盆景),很漂亮吧!你将不同的种子放入花盆,一段时间后你就可以看到各种美丽的鲜花了,不同种子所生产出来的鲜花有不同的花朵、叶子和枝茎。编码该如何实现呢? 设计目标:将种子放入花盆,一段时间后就可以收获美丽的鲜花!2.不假思索的思路:将... 阅读全文
posted @ 2010-11-26 12:50 天津城建学院软件工程 阅读(1256) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息姓名:周智学号:07770108二、模式名称适配器模式三、模式介绍定义:在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。分类:对象适配器模式 - 在这种适配器模式中,适配器容纳一个它我包裹的类的实例。在这种情况下,适配器调用被包裹对象的物... 阅读全文
posted @ 2010-11-25 16:21 天津城建学院软件工程 阅读(127) | 评论 (0) 编辑
工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:工厂模式模式概述: 当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用工厂方法模式来设计系统。工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。工厂方法模式的结构中包括四种角色。●... 阅读全文
posted @ 2010-11-21 22:31 天津城建学院软件工程 阅读(49) | 评论 (0) 编辑
简单工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:简单工厂模式模式概述: 简单工厂模式的实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品类的实例。简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色三个参与者。● 工厂(Creator)角色是简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。● 抽象产品(Prod... 阅读全文
posted @ 2010-11-21 21:01 天津城建学院软件工程 阅读(55) | 评论 (0) 编辑
桥接模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:桥接模式2、模式概述: Bridge桥接模式是一种结构型模式,它主要应对的是:由于类型的固有罗辑,使得类型具有两个或两个以上的纬度变化。也就是要求抽象不应依赖于实现细节,实现细节应依赖于抽象。桥接模式包括四种角色。● 抽象(Abstraction):是一个抽象类,该抽象类含有Implementor声明的变量,即维护一个Im... 阅读全文
posted @ 2010-11-21 18:57 天津城建学院软件工程 阅读(59) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:适配器模式2、模式概述: 在现实生活中往往会遇到这样的问题:很多设备需要使用同一种资源,但每一种设备使用这种资源时都需要特定的接口,这些接口都不一样。现在的问题是怎样实现在没有对应接口的情况下也使设备能够使用呢?这时就可以用到适配器模式。3、定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接... 阅读全文
posted @ 2010-11-21 18:52 天津城建学院软件工程 阅读(118) | 评论 (0) 编辑
原型模式
摘要: 一、完成者信息姓名:赖春林学号:07770110二、模式信息1、模式名称:原型模式2、模式概述: 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?3、定义:用原型实例指定创建对象的种类,并且通过拷... 阅读全文
posted @ 2010-11-21 18:36 天津城建学院软件工程 阅读(78) | 评论 (2) 编辑
观察者模式
摘要: 一、完成者信息:姓名:周义学号:07770207二、模式信息模式名称:观察者模式模式概述: 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依... 阅读全文
posted @ 2010-11-21 17:10 天津城建学院软件工程 阅读(134) | 评论 (0) 编辑
访问者模式 Visitor Pattern
摘要: 访问者模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的访问者模式。 在介绍访问者模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:有一天,有两个不同公司的业务员来到两家相同的公司进行业务商讨。两个业务员对同一个公司的业务不相同。试着编程实现给过程。 倘若您作为编写者,一般情况下您会如何来处理这个问题 我在这里展示我的不假思索的解决方... 阅读全文
posted @ 2010-11-01 12:28 天津城建学院软件工程 阅读(94) | 评论 (0) 编辑
10 2010 档案
策略模式
摘要: 策略模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的策略模式。 介绍策略模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:如今网购盛行,很多人都应该在网上买过东西,虚拟物品或者是非虚拟物品。在B2C的网络购物网站中,商家为了吸引买家常会推出比较优惠的折扣。现在有家B2C的购物网站,它的折扣方式是这样的,对于VIP来说基本的折扣率是20%... 阅读全文
posted @ 2010-10-31 16:32 天津城建学院软件工程 阅读(199) | 评论 (0) 编辑
适配器模式
摘要: 姓名:赵汉青学号:07770201模式名称:适配器模式1.问题描述生活场景:日常生活中,我们所使用的电器,比如:手机,笔记本电脑,剃须刀等在充电时所需要的电压,均不是我国提供的统一民用电压“220v”,而我们又只能使用已经存在的电压给电器充电,这时,就需要一个电源适配,把220V的电压转化为电器所需的电压值。设计目标:实现对不能满足新化境的“已存对象&rdquo... 阅读全文
posted @ 2010-10-26 00:07 天津城建学院软件工程 阅读(178) | 评论 (2) 编辑
抽象工厂模式
摘要: 姓名:赵汉青学号:07770201模式名称:抽象工厂模式1.问题描述生活场景:某家具厂为学校生产课桌和座椅,开始只生产木质的课桌和座椅,后来经学校要求,又开始为学校生产铁质的课桌和座椅。设计目标:实现针对多种成套产品的生产,每套产品有多种不同等级结构的物品组成。2.不假思索的思路思路描述:通过简单工厂的模式来实现。即在生产木质课桌的工厂里加开生产铁质课桌的生产线;在生产木质椅子的工厂里加开生产铁质... 阅读全文
posted @ 2010-10-21 23:24 天津城建学院软件工程 阅读(151) | 评论 (1) 编辑
工厂方法模式
摘要: 姓名:赵汉青学号:07770201模式名称:工厂方法模式1.问题描述生活场景:很多的公司都通过生产不同品牌的同一类产品来占有市场,比如,联合利华公司生产洗发水,开始只有“夏士莲”系列,后来为了在洗发水市场上扩充份额,又推出了“清扬”系列。你会发现,不管是“清扬”还是“夏士莲”,有着相同的功能&mdash... 阅读全文
posted @ 2010-10-21 23:13 天津城建学院软件工程 阅读(475) | 评论 (0) 编辑
test
摘要: test 阅读全文
posted @ 2010-10-11 15:49 天津城建学院软件工程 阅读(21) | 评论 (0) 编辑
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did48995
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
(2)适用性
1. 当 创建复杂对象的算法 应该 独立于该对象的组成部分以及他们的装配方式 ;
2. 当构造过程必须允许 构造的对象有不同的表示 ;
(3)结构
(4)参与者
Builder:为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder:1. 实现Builder的接口以构造和装配该产品的各个部件
2. 定义并明确它所创建的表示
3. 提供一个检索产品的接口
Director:构造一个使用Builder接口的对象
Product:1.表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程
2.包含定义组成部件的类,包括将这些部件装配成最终产品的接口
(5)协作
下面序列图说明了Builder和Director是如何与一个客户协作的
代码示例
(1)示例简述
前段时间看了电影《超级战舰》,还不错,所以在举例子的时候就想到用builder模式构建一艘船。注意是“船”,我没说构建“战舰”,船的范围就大了,比如有:航母、驱逐舰、潜艇,当然也包括补给船等后勤船只。而不同的船构造也不同,航母上首先有小飞机,玩过星际的人都知道,还有许多电子设备和一些防空武器;驱逐舰上有鱼雷、导弹、防空炮等等。可以说船的构造还是相对比较复杂的。
那么今天的目的就是: 运用builder模式来造一艘“船”。
回忆下Gof对builder模式的描述:“ 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 ”。有这么几个关键点:1. 对象比较复杂,内部可能包含多个元素或者多个其他对象的组合。2. 对象的表示可能有多种,并且有需求在多种表示中进行切换。3.使用同样的构造过程来创建可能的不同表示。
这样看来,“造一艘船”这个事件中,复杂对象指的是不同种类“船”,“船”的内部可能包括其他对象:“鱼雷”、“飞机”等;“船”有多种表示;相同的构建过程则是描述“造船”这个事件的抽象过程,隐藏具体的构造细节,这样才能通过相同的构造过程得到不同的“船”的表示。
(2)示例说明
首先需要定义下船只的构造规则,方便示例的说明,如下:
航母(AircraftCarrier) = n * 飞机(Aircraft) + n * 防空炮(FlakCannon) + 船体(Hull) + n * 设备(Equipment);
驱逐舰(Destroyer) = n * 鱼雷(Torpedo) + n * 防空炮(FlakCannon) + n * 导弹(Missile) + 船体(Hull) + n * 设备(Equipment);
补给船(Tender) = 船体(Hull) + n * 设备(Equipment);
为什么都是n呢?当然是因为不止一个了!
其实这点非常重要!!!在前面结构图中关于导向器(Director)的描述是这样的:
1: for all objects in structure {
2: builder -> buildPart();
3: }
注意这个for,为什么不直接是buildPart()调用,而要循环调用呢?我个人的理解是这样的,每 一类 对象会有一个具体的生成器(ConcreteBuilder)来构造,新增 一类 对象时,也需要新增一个具体的生成器(ConcreteBuilder)。那么对于对象的 类别 应该是根据构造结构来分,而不是根据构造结构的不同数量来分,例如五架飞机的航母和十架飞机的航母构造应该是由同一个具体的航母生成器来完成,而不需要新建另一个具体的生成器。组件数量不同的构造过程应该是在导向器(Director)中根据不同的构造算法来实现的。
为什么会特别关注这个细节,是因为看的一些书和资料有的忽略了这点,代码例子看起来很漂亮,但是细细一想由于数量不同带来的大量新建具体生成器的问题就出来了,我想这显然不是GOF的本意。这里有篇文章写的很好 点击 。
再来看下结构图:
(3)示例代码
废话了这么多该贴代码了:
先是船的一些组件代码,加了很简单的打印。
1: /**
2: * <飞机>
3: */
4: public class Aircraft
5: {
6: public Aircraft( int no)
7: {
8: System.out.println( "生产了编号为" + no + "的战斗机" );
9: }
10: }
1: /**
2: * <各种设备>
3: */
4: public class Equipment
5: {
6: public Equipment( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的设备" );
9: }
10: }
1: /**
2: * <防空炮>
3: */
4: public class FlakCannon
5: {
6: public FlakCannon( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的防空炮" );
9: }
10: }
1: /**
2: * <船体>
3: */
4: public class Hull
5: {
6: public Hull()
7: {
8: System.out.println( "制造了主船体" );
9: }
10: }
1: /**
2: * <导弹>
3: */
4: public class Missile
5: {
6: public Missile( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的导弹" );
9: }
10: }
1: /**
2: * <鱼雷>
3: */
4: public class Torpedo
5: {
6: public Torpedo( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的鱼雷" );
9: }
10: }
再来看下船的代码,具体表示为:航母、驱逐舰、补给船:
1: /**
2: * <航母对象>
3: */
4: public class AircraftCarrier
5: {
6: //航母名称
7: private String name;
8:
9: //舰载飞机
10: private List<Aircraft> aircrafts;
11:
12: //防空炮
13: private List<FlakCannon> flakCannons;
14:
15: //船体
16: private Hull hull;
17:
18: //设备
19: private List<Equipment> equipments;
20:
21: public AircraftCarrier(String name)
22: {
23: this .name = name;
24: equipments = new ArrayList<Equipment>();
25: aircrafts = new ArrayList<Aircraft>();
26: flakCannons = new ArrayList<FlakCannon>();
27: }
28: //get/set方法忽略
29: }
1: /**
2: * <驱逐舰对象>
3: */
4: public class Destroyer
5: {
6: //驱逐舰编号
7: private String name;
8:
9: //防空炮
10: private List<FlakCannon> flakCannons;
11:
12: //船体
13: private Hull hull;
14:
15: //设备
16: private List<Equipment> equipments;
17:
18: //鱼雷
19: private List<Torpedo> torpedos;
20:
21: //导弹
22: private List<Missile> missiles;
23:
24: public Destroyer(String name)
25: {
26: this .name = name;
27: equipments = new ArrayList<Equipment>();
28: flakCannons = new ArrayList<FlakCannon>();
29: torpedos = new ArrayList<Torpedo>();
30: missiles = new ArrayList<Missile>();
31: }
32: //get/set方法省略
33: }
1: /**
2: * <补给船>
3: */
4: public class Tender
5: {
6: //补给船名称
7: private String name;
8:
9: //船体
10: private Hull hull;
11:
12: //设备
13: private List<Equipment> equipments;
14:
15: public Tender(String name)
16: {
17: this .name = name;
18: equipments = new ArrayList<Equipment>();
19: }
20:
21: //get/set方法省略
22: }
下面是生成器(Builder)的代码:
1: /**
2: * <舰船Builder>
3: */
4: public abstract class ShipBuilder
5: {
6: //建造船
7: public abstract void buildShip(String name);
8:
9: //建造船体
10: public abstract void buildHull();
11:
12: //建造设备
13: public abstract void buildEquipment( int no);
14:
15: //建造导弹
16: public abstract void buildMissile( int no);
17:
18: //建造鱼雷
19: public abstract void buildTorpedo( int no);
20:
21: //建造飞机
22: public abstract void buildAircraft( int no);
23:
24: //建造防空炮
25: public abstract void buildFlakCannon( int no);
26:
27: //返回结果
28: public abstract Object getResult();
29: }
生成器可以是抽象类也可以是接口,再来看下几个具体生成器的代码(ConcreteBuilder):
1: /**
2: * <建造航母类>
3: */
4: public class AircraftCarrierBuilder extends ShipBuilder
5: {
6: private AircraftCarrier aircraftCarrier;
7:
8: public void buildShip(String name)
9: {
10: this .aircraftCarrier = new AircraftCarrier(name);
11: }
12:
13: public AircraftCarrier getResult()
14: {
15: System.out.println( "\"" + aircraftCarrier.getName() + "\"号航母制造完成" );
16: return aircraftCarrier;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22: this .aircraftCarrier.getAircrafts().add( new Aircraft(no));
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .aircraftCarrier.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .aircraftCarrier.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .aircraftCarrier.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
1: /**
2: * <驱逐舰建造>
3: */
4: public class DestoryerBuilder extends ShipBuilder
5: {
6: private Destroyer destroyer;
7:
8: public void buildShip(String name)
9: {
10: this .destroyer = new Destroyer(name);
11: }
12:
13: public Destroyer getResult()
14: {
15: System.out.println( "\"" + destroyer.getName() + "\"号驱逐舰制造完成" );
16: return destroyer;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .destroyer.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .destroyer.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .destroyer.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46: this .destroyer.getMissiles().add( new Missile(no));
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52: this .destroyer.getTorpedos().add( new Torpedo(no));
53: }
54: }
1: /**
2: * <补给船建造类>
3: */
4: public class TenderBuilder extends ShipBuilder
5: {
6: private Tender tender;
7:
8: public void buildShip(String name)
9: {
10: this .tender = new Tender(name);
11: }
12:
13: public Tender getResult()
14: {
15: System.out.println( "\"" + tender.getName() + "\"号补给船制造完成" );
16: return tender;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .tender.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34:
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .tender.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
大家也许注意到了,3个具体生成器中存在空方法,比如在航母生成器中的buildMissile和buildTorpedo,因为我们定义的在航母上没有导弹和鱼雷。
GOF在设计模式中举的例子是用C写的,生成器父类里使用了虚函数,有点像java的abstract,在具体生成器子类中可以选择性的重写父类方法,但是java中没有虚函数,所以只能采用接口或者抽象类,那么在子类中必须实现所有的方法,所以我只能给空的实现了。
再来看一下导向器的代码,在导向器中要对Builder进行配置,并如前面结构图中所画的,在导向器中定义了各种构造的算法:
1: /**
2: * Director
4: */
5: public class ShipFactory
6: {
7: private ShipBuilder shipBuilder;
8:
9: public ShipFactory(ShipBuilder shipBuilder)
10: {
11: this .shipBuilder = shipBuilder;
12: }
13:
14: public void createShip( int shipType, String name)
15: {
16: shipBuilder.buildShip(name);
17: shipBuilder.buildHull();
18: switch (shipType)
19: {
20: //中国航母
21: case 1:
22: buildAircraftCarrierCHN();
23: break ;
24: //外国航母
25: case 2:
26: buildAircraftCarrierUSA();
27: break ;
28: //驱逐舰
29: case 3:
30: buildDrstroyer();
31: break ;
32: //补给船
33: case 4:
34: buildTender();
35: break ;
36: }
37: }
38:
39: private void buildAircraftCarrierCHN()
40: {
41: for ( int i=1; i<6; i++)
42: {
43: shipBuilder.buildEquipment(i);
44: }
45: for ( int i=1; i<11; i++)
46: {
47: shipBuilder.buildAircraft(i);
48: }
49: for ( int i=1; i<11; i++)
50: {
51: shipBuilder.buildFlakCannon(i);
52: }
53: }
54:
55: private void buildAircraftCarrierUSA()
56: {
57: for ( int i=1; i<7; i++)
58: {
59: shipBuilder.buildEquipment(i);
60: }
61: for ( int i=1; i<12; i++)
62: {
63: shipBuilder.buildAircraft(i);
64: }
65: for ( int i=1; i<12; i++)
66: {
67: shipBuilder.buildFlakCannon(i);
68: }
69: }
70:
71: private void buildTender()
72: {
73: for ( int i=1; i<6; i++)
74: {
75: shipBuilder.buildEquipment(i);
76: }
77: }
78:
79: private void buildDrstroyer()
80: {
81: for ( int i=1; i<6; i++)
82: {
83: shipBuilder.buildEquipment(i);
84: }
85: for ( int i=1; i<12; i++)
86: {
87: shipBuilder.buildMissile(i);
88: }
89: for ( int i=1; i<12; i++)
90: {
91: shipBuilder.buildFlakCannon(i);
92: }
93: for ( int i=1; i<12; i++)
94: {
95: shipBuilder.buildTorpedo(i);
96: }
97: }
98: }
最后看下使用的代码:
1: public class Client
2: {
3: public static void main(String[] args)
4: {
5: ShipBuilder builder = new AircraftCarrierBuilder();
6: // ShipBuilder builder = new DestoryerBuilder();
7: // ShipBuilder builder = new TenderBuilder();
8: ShipFactory factory = new ShipFactory(builder);
9: factory.createShip(1, "和谐" );
10: // factory.createShip(2, "圣母玛利亚");
11: // factory.createShip(3, "牛逼号");
12: // factory.createShip(4, "龙套号");
13: builder.getResult();
14: }
15: }
运行结果:
1: 制造了主船体
2: 制造了编号为1的设备
3: 制造了编号为2的设备
4: 制造了编号为3的设备
5: 制造了编号为4的设备
6: 制造了编号为5的设备
7: 生产了编号为1的战斗机
8: 生产了编号为2的战斗机
9: 生产了编号为3的战斗机
10: 生产了编号为4的战斗机
11: 生产了编号为5的战斗机
12: 生产了编号为6的战斗机
13: 生产了编号为7的战斗机
14: 生产了编号为8的战斗机
15: 生产了编号为9的战斗机
16: 生产了编号为10的战斗机
17: 制造了编号为1的防空炮
18: 制造了编号为2的防空炮
19: 制造了编号为3的防空炮
20: 制造了编号为4的防空炮
21: 制造了编号为5的防空炮
22: 制造了编号为6的防空炮
23: 制造了编号为7的防空炮
24: 制造了编号为8的防空炮
25: 制造了编号为9的防空炮
26: 制造了编号为10的防空炮
27: "和谐" 号航母制造完成
至此代码示例就结束了。
一些思考
(1)产品(Product)需不需要抽象类?
GOF给出了答案: 通常情况下,由具体生成器生成的产品,它们的表示相差是如此之大以至于给不同的产品以公共父类没有太大意思。
上面船的例子可能不太贴切,毕竟船之间会有公共的东西,但是换个其他的例子比如构造一副画,不同的画之间很难有共同之处,所以给它们公共接口是没有意义的,它们也不需要这样的接口。因为客户通常用合适的具体生成器来配置导向器,客户的位置使得它很容易的就知道Builder的哪个具体子类被使用和能相应的处理它的产品
(2)多重Builder?
在写上面的例子的时候我是颇有些疑问的,船是由船体、设备、武器等构造出来的,而船体、设备、武器等也是由其他级别更低的组件构造的,它们之间也存在着复杂的构造关系。这中间可能有好几层,知道追溯到螺丝、螺母这样的原子级零件,每一层复杂的构造关系都可以用Builder模式表示。而往上,多艘船可以构造成一个舰队;多个舰队构造成海军等等。
于是我陷入了疑惑,这样多层的Builder模式我该如何表示?直到我看到了一句话: Composite模式通常是由Builder生成的 。原来这样多重的Builder关系已经属于另外一种模式了,那么就论Builder模式的话,我们只需要关注其中的一层构造过程就可以了。
关于Builder模式就这么多了,虽然这个模式好像并不经常用。自己理解了Builder模式有一段时间,自觉理解的并不透彻,有些地方还是生搬硬套,也没有实际运用的场景和经验,有一些思考,有一些疑问,希望大家补全,互相学习。
我只是走在路上,偶尔驻足观赏,偶尔回头看看。
分类: 设计模式 , Java相关
http://www.cnblogs.com/tjcjxy/archive/2010/10/31/1865626.html
12 2010 档案
代理模式
摘要: 一、完成者信息:姓名:杨郅昱学号:07770121二、模式信息模式名称:代理模式生活场景:判定是否是三角形然后求出面积:任意给定三个数,先判断是否能构成三角形 如果能构成三角形,在求出三角形的面积。1.不假思索的思路:通过类继承的方式来做上面的例子。即:任意给定三个数字, 用一个类继承运算接口,先判定能否构成三角形,如果能,求出面积;如果不能,则停止运行。2.类结构图:代码浏览:代码1. 存在问题:1. 当调入大量信息时会发费很长时间。2. 进行判定和计算都在一个类中进行,需要大量的时间。3. 如果判定规则变动,则需要大量的修改。2.归纳阶段归纳步骤一当前目标:实现通过一个代理来处理请求,并将 阅读全文
posted @ 2010-12-16 15:15 天津城建学院软件工程 阅读(46) | 评论 (0) 编辑
桥接模式
摘要: 姓名:陈阳学号:07770114一、模式信息模式名称:桥接模式生活场景:考虑一个售楼小区不同的建筑面积、不同楼层的每平米造价成本是不同的。同一建筑面积的屋子,有楼层的高低之分。而同一楼层也会有建筑面积不一样的屋子终极目标:实现适应于扩充到对各种建筑面积的屋子和各种楼层进行建模的情形。1.不假思索的思路:通过类继承的方式来做上面的例子。即:先建立楼层类;然后派生出高楼层类、矮楼层类;然后再高楼层类和矮楼层类上分别派生出:大面积房屋类和小面积房屋类。类结构图:代码浏览:代码存在问题:1.它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有 阅读全文
posted @ 2010-12-15 17:12 天津城建学院软件工程 阅读(20) | 评论 (0) 编辑
迭代器模式
摘要: 一、完成者信息:姓名: 王延学号:07770125二、模式信息模式名称:迭代器生活场景:将保险柜里的钱分类,从中选出假币。终极目标:合计最终真币的总数。 1.不假思索的思路:通过类和类之间参数的调用来实现最后结果。类结构图:代码浏览:代码:存在问题:1.计算过程过于复杂。2.类Real的实用性很差,可以直接去掉。3.继承和调用的次数过多,容易混乱。4.new的对象名过多,容易混搅。2.归纳阶段归纳步骤一、二、四当前目标:实现假币的计算和最后的总和思路:类结构图:代码浏览:代码:设计体会:节省了很多不必要的步骤,是过程简明了很多。减少了出错的可能性,是程序的耦合程度大大减少。 验证结论:用户使用 阅读全文
posted @ 2010-12-15 16:46 天津城建学院软件工程 阅读(16) | 评论 (0) 编辑
享元模式
摘要: 一、完成者信息:姓名:王智超学号:07770120二、模式信息模式名称:享元模式生活场景:考虑生产汽车的场景:一个品牌有各种型号的汽车,每种型号的汽车有相同的参数(如型号,长,宽,高),也有不同的参数(如颜色,马力) ,就可以把相同的参数拿出来共享。终极目标:实现适应于扩充到对各种汽车和各种型号进行建模的情形。1.不假思索的思路:通过给属性赋值的方法来做:没一辆车都有自己的所有的参数的属性。 类结构图: 代码浏览:代码实现:客户端调用: 存在问题: 1.重复代码会很多,相同的型号汽车有一部分参数是相同的; 2.类的结构过于复杂,难于维护; 3.最致命的一点是效率太差。生产大量汽车会创 阅读全文
posted @ 2010-12-15 16:18 天津城建学院软件工程 阅读(41) | 评论 (0) 编辑
装饰模式
摘要: 一、完成者信息:姓名:张璐璐学号:07770232二、模式信息模式名称:装饰模式生活场景:加工蛋糕的场景:现有烤好的蛋糕,接下来我们要给蛋糕切好形状,然后涂上奶油或巧克力,再放上草莓,最后插上蜡烛。1.不假思索的思路: 按类继承的作法如下:类图:代码存在问题:由此可见,如果用类继承实现,子类会爆炸式地增长。动机(Motivate):上述描述的问题根源在于我们“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态物质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能组合)会导致更多子类的膨胀(多继承)。2.归纳阶段如何使“对象功能的扩展”能够根据 阅读全文
posted @ 2010-12-15 15:45 天津城建学院软件工程 阅读(38) | 评论 (1) 编辑
模板方法模式
摘要: 一、完成者信息姓名:陈绯学号:07770230二、模式信息模式名称:模板方法模式1.问题描述生活场景:大家都经常会用到对数据库中表进行操作,有时候数据库中有若干个表,我们往往是一个一个的对相应的表进行连接数据库,然后对指定的表进行增、删、改、查的一系列操作,组后关闭数据库的连接。但是当我们要对大型的数据库进行这些操作的时候,你会发现这些操作很繁琐,要对每一个表都进行相同的处理,加大的数据的操作工作。设计目的:实现对若干个不相同的表进行重复的增删改查工作。2.不假思索的思路思路描述:对TemplateMethod数据库中的Categories表进行数据库的连接,表的增删改查以及数据库的关闭等操作 阅读全文
posted @ 2010-12-09 16:52 天津城建学院软件工程 阅读(325) | 评论 (0) 编辑
访问者模式
摘要: 一、完成者信息:姓名:王璐学号:07770231二、模式信息模式名称:访问者模式生活场景:假如以前食堂的食品和饮料一直都是一个价位,没有变动。这学期开学,由于工商局调节价位,导致普遍商品都涨价了,所以学校食堂里,菜价和饮料都涨价了。终极目标:实现能够对所有的情况进行访问,通知发生变化。不使用访问者模式不假思索的思路:我们去吃饭,首先看菜单,来选择食物,用现在的菜单跟以前的菜单相对比,价位之间的变化。类结构图:代码实现:代码运行结果:存在问题:在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的改变,将会给子类带来很繁重的变更负担,甚至破坏原有 阅读全文
posted @ 2010-12-09 13:07 天津城建学院软件工程 阅读(135) | 评论 (0) 编辑
装饰模式
摘要: 姓名:高振松学号:077701161、生活场景:看过美国科幻片的同学应该都会为美国人那惊人的想象力说折服吧。在美国的科幻片里有一种东西会经常在镜头里出现,那就是会飞行的交通工具(汽车,卡车之类的)。这些交通工具既可以在陆地上跑,也可以在天空中飞行或者在水中行驶。现假设,现在有一家汽车生产商,最近突破一项关键技术,使得所有类型的车辆都可以在天空中飞或者在水中行驶的功能。而你正好在给该生产商开发系统软... 阅读全文
posted @ 2010-12-01 21:49 天津城建学院软件工程 阅读(155) | 评论 (0) 编辑
代理模式
摘要: 姓名:宁前程学号:07770118模式名称:代理模式1.问题描述生活场景:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买,不但买不到自己想要的衣服,还白白的跑了一趟。设计目的:让用户不必非要跑到李宁公司总部去购买。2.不假思索的思路思路描述:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买。类结构图:缺点:这样的设计,为公司造成很多麻烦,也为自己造成很多麻烦。代码:首先定义一个能产生... 阅读全文
posted @ 2010-12-01 21:28 天津城建学院软件工程 阅读(45) | 评论 (0) 编辑
11 2010 档案
闲谈责任链模式
摘要: 责任链模式是使用多个对象处理用户请求的成熟模式,责任链模式的关键是将用户的请求分派给许多对象,这些对象被组织成一个责任链,即每个对象含有后继对象的引用,并要求责任链上的每个对象,如果能处理用户的请求,就做出处理,不再将用户的请求传递给责任链上的下一个对象,如果不能处理用户的请求,就必须将用户的请求传递给责任链上的下一个对象。 阅读全文
posted @ 2010-11-30 23:59 天津城建学院软件工程 阅读(183) | 评论 (0) 编辑
生产器模式
摘要: 作者:苏石 07770107模式名称生产器模式模式介绍生成器(Builder)模式,也被称为建造者模式或构造器模式,属于创建型模式,它是将一个复杂的对象的构造与这个复杂对象的表示分离开 ,使得同样的构建构成可以创建不同的表示。问题提出生活场景:仍以生产洗发水为例,原生产的洗发水只有一种类型,比如:功效是去屑,包装都是一样的。但随着科技的发展、消费水平的提升,只生产这种单一类型的洗发水已经不能满足当... 阅读全文
posted @ 2010-11-30 17:02 天津城建学院软件工程 阅读(116) | 评论 (0) 编辑
Template Method Pattern 模版方法模式
摘要: Template MethodPattern作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的模版方法模式。 问题:现在有一家汽车生产商需要一个管理汽车生产的管理软件。其中在该系统中有一个管理组装汽车的子模块。该模块要能根据不同的汽车类型来组装相应的汽车。汽车的被组装部分分别是汽车的车盖,车地盘,后备箱,车胎。现在来试着实现下该过程。 根据上面的描述,我在这里选择里... 阅读全文
posted @ 2010-11-28 16:15 天津城建学院软件工程 阅读(240) | 评论 (2) 编辑
生成器模式(又名建造者模式、Builder Pattern)
摘要: 姓名:谭鹏飞学号:07770106模式名称:生成器模式1.问题描述生活场景:你玩过种地、种花等类似的游戏吗?这是最近很流行的游戏哟!下面就是从种花游戏中剪切的四个花盆(盆景),很漂亮吧!你将不同的种子放入花盆,一段时间后你就可以看到各种美丽的鲜花了,不同种子所生产出来的鲜花有不同的花朵、叶子和枝茎。编码该如何实现呢? 设计目标:将种子放入花盆,一段时间后就可以收获美丽的鲜花!2.不假思索的思路:将... 阅读全文
posted @ 2010-11-26 12:50 天津城建学院软件工程 阅读(1256) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息姓名:周智学号:07770108二、模式名称适配器模式三、模式介绍定义:在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。分类:对象适配器模式 - 在这种适配器模式中,适配器容纳一个它我包裹的类的实例。在这种情况下,适配器调用被包裹对象的物... 阅读全文
posted @ 2010-11-25 16:21 天津城建学院软件工程 阅读(127) | 评论 (0) 编辑
工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:工厂模式模式概述: 当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用工厂方法模式来设计系统。工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。工厂方法模式的结构中包括四种角色。●... 阅读全文
posted @ 2010-11-21 22:31 天津城建学院软件工程 阅读(49) | 评论 (0) 编辑
简单工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:简单工厂模式模式概述: 简单工厂模式的实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品类的实例。简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色三个参与者。● 工厂(Creator)角色是简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。● 抽象产品(Prod... 阅读全文
posted @ 2010-11-21 21:01 天津城建学院软件工程 阅读(55) | 评论 (0) 编辑
桥接模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:桥接模式2、模式概述: Bridge桥接模式是一种结构型模式,它主要应对的是:由于类型的固有罗辑,使得类型具有两个或两个以上的纬度变化。也就是要求抽象不应依赖于实现细节,实现细节应依赖于抽象。桥接模式包括四种角色。● 抽象(Abstraction):是一个抽象类,该抽象类含有Implementor声明的变量,即维护一个Im... 阅读全文
posted @ 2010-11-21 18:57 天津城建学院软件工程 阅读(59) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:适配器模式2、模式概述: 在现实生活中往往会遇到这样的问题:很多设备需要使用同一种资源,但每一种设备使用这种资源时都需要特定的接口,这些接口都不一样。现在的问题是怎样实现在没有对应接口的情况下也使设备能够使用呢?这时就可以用到适配器模式。3、定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接... 阅读全文
posted @ 2010-11-21 18:52 天津城建学院软件工程 阅读(118) | 评论 (0) 编辑
原型模式
摘要: 一、完成者信息姓名:赖春林学号:07770110二、模式信息1、模式名称:原型模式2、模式概述: 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?3、定义:用原型实例指定创建对象的种类,并且通过拷... 阅读全文
posted @ 2010-11-21 18:36 天津城建学院软件工程 阅读(78) | 评论 (2) 编辑
观察者模式
摘要: 一、完成者信息:姓名:周义学号:07770207二、模式信息模式名称:观察者模式模式概述: 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依... 阅读全文
posted @ 2010-11-21 17:10 天津城建学院软件工程 阅读(134) | 评论 (0) 编辑
访问者模式 Visitor Pattern
摘要: 访问者模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的访问者模式。 在介绍访问者模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:有一天,有两个不同公司的业务员来到两家相同的公司进行业务商讨。两个业务员对同一个公司的业务不相同。试着编程实现给过程。 倘若您作为编写者,一般情况下您会如何来处理这个问题 我在这里展示我的不假思索的解决方... 阅读全文
posted @ 2010-11-01 12:28 天津城建学院软件工程 阅读(94) | 评论 (0) 编辑
10 2010 档案
策略模式
摘要: 策略模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的策略模式。 介绍策略模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:如今网购盛行,很多人都应该在网上买过东西,虚拟物品或者是非虚拟物品。在B2C的网络购物网站中,商家为了吸引买家常会推出比较优惠的折扣。现在有家B2C的购物网站,它的折扣方式是这样的,对于VIP来说基本的折扣率是20%... 阅读全文
posted @ 2010-10-31 16:32 天津城建学院软件工程 阅读(199) | 评论 (0) 编辑
适配器模式
摘要: 姓名:赵汉青学号:07770201模式名称:适配器模式1.问题描述生活场景:日常生活中,我们所使用的电器,比如:手机,笔记本电脑,剃须刀等在充电时所需要的电压,均不是我国提供的统一民用电压“220v”,而我们又只能使用已经存在的电压给电器充电,这时,就需要一个电源适配,把220V的电压转化为电器所需的电压值。设计目标:实现对不能满足新化境的“已存对象&rdquo... 阅读全文
posted @ 2010-10-26 00:07 天津城建学院软件工程 阅读(178) | 评论 (2) 编辑
抽象工厂模式
摘要: 姓名:赵汉青学号:07770201模式名称:抽象工厂模式1.问题描述生活场景:某家具厂为学校生产课桌和座椅,开始只生产木质的课桌和座椅,后来经学校要求,又开始为学校生产铁质的课桌和座椅。设计目标:实现针对多种成套产品的生产,每套产品有多种不同等级结构的物品组成。2.不假思索的思路思路描述:通过简单工厂的模式来实现。即在生产木质课桌的工厂里加开生产铁质课桌的生产线;在生产木质椅子的工厂里加开生产铁质... 阅读全文
posted @ 2010-10-21 23:24 天津城建学院软件工程 阅读(151) | 评论 (1) 编辑
工厂方法模式
摘要: 姓名:赵汉青学号:07770201模式名称:工厂方法模式1.问题描述生活场景:很多的公司都通过生产不同品牌的同一类产品来占有市场,比如,联合利华公司生产洗发水,开始只有“夏士莲”系列,后来为了在洗发水市场上扩充份额,又推出了“清扬”系列。你会发现,不管是“清扬”还是“夏士莲”,有着相同的功能&mdash... 阅读全文
posted @ 2010-10-21 23:13 天津城建学院软件工程 阅读(475) | 评论 (0) 编辑
test
摘要: test 阅读全文
posted @ 2010-10-11 15:49 天津城建学院软件工程 阅读(21) | 评论 (0) 编辑
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did48995
1. 当 创建复杂对象的算法 应该 独立于该对象的组成部分以及他们的装配方式 ;
2. 当构造过程必须允许 构造的对象有不同的表示 ;
(3)结构
(4)参与者
Builder:为创建一个Product对象的各个部件指定抽象接口
ConcreteBuilder:1. 实现Builder的接口以构造和装配该产品的各个部件
2. 定义并明确它所创建的表示
3. 提供一个检索产品的接口
Director:构造一个使用Builder接口的对象
Product:1.表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程
2.包含定义组成部件的类,包括将这些部件装配成最终产品的接口
(5)协作
下面序列图说明了Builder和Director是如何与一个客户协作的
代码示例
(1)示例简述
前段时间看了电影《超级战舰》,还不错,所以在举例子的时候就想到用builder模式构建一艘船。注意是“船”,我没说构建“战舰”,船的范围就大了,比如有:航母、驱逐舰、潜艇,当然也包括补给船等后勤船只。而不同的船构造也不同,航母上首先有小飞机,玩过星际的人都知道,还有许多电子设备和一些防空武器;驱逐舰上有鱼雷、导弹、防空炮等等。可以说船的构造还是相对比较复杂的。
那么今天的目的就是: 运用builder模式来造一艘“船”。
回忆下Gof对builder模式的描述:“ 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 ”。有这么几个关键点:1. 对象比较复杂,内部可能包含多个元素或者多个其他对象的组合。2. 对象的表示可能有多种,并且有需求在多种表示中进行切换。3.使用同样的构造过程来创建可能的不同表示。
这样看来,“造一艘船”这个事件中,复杂对象指的是不同种类“船”,“船”的内部可能包括其他对象:“鱼雷”、“飞机”等;“船”有多种表示;相同的构建过程则是描述“造船”这个事件的抽象过程,隐藏具体的构造细节,这样才能通过相同的构造过程得到不同的“船”的表示。
(2)示例说明
首先需要定义下船只的构造规则,方便示例的说明,如下:
航母(AircraftCarrier) = n * 飞机(Aircraft) + n * 防空炮(FlakCannon) + 船体(Hull) + n * 设备(Equipment);
驱逐舰(Destroyer) = n * 鱼雷(Torpedo) + n * 防空炮(FlakCannon) + n * 导弹(Missile) + 船体(Hull) + n * 设备(Equipment);
补给船(Tender) = 船体(Hull) + n * 设备(Equipment);
为什么都是n呢?当然是因为不止一个了!
其实这点非常重要!!!在前面结构图中关于导向器(Director)的描述是这样的:
1: for all objects in structure {
2: builder -> buildPart();
3: }
注意这个for,为什么不直接是buildPart()调用,而要循环调用呢?我个人的理解是这样的,每 一类 对象会有一个具体的生成器(ConcreteBuilder)来构造,新增 一类 对象时,也需要新增一个具体的生成器(ConcreteBuilder)。那么对于对象的 类别 应该是根据构造结构来分,而不是根据构造结构的不同数量来分,例如五架飞机的航母和十架飞机的航母构造应该是由同一个具体的航母生成器来完成,而不需要新建另一个具体的生成器。组件数量不同的构造过程应该是在导向器(Director)中根据不同的构造算法来实现的。
为什么会特别关注这个细节,是因为看的一些书和资料有的忽略了这点,代码例子看起来很漂亮,但是细细一想由于数量不同带来的大量新建具体生成器的问题就出来了,我想这显然不是GOF的本意。这里有篇文章写的很好 点击 。
再来看下结构图:
(3)示例代码
废话了这么多该贴代码了:
先是船的一些组件代码,加了很简单的打印。
1: /**
2: * <飞机>
3: */
4: public class Aircraft
5: {
6: public Aircraft( int no)
7: {
8: System.out.println( "生产了编号为" + no + "的战斗机" );
9: }
10: }
1: /**
2: * <各种设备>
3: */
4: public class Equipment
5: {
6: public Equipment( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的设备" );
9: }
10: }
1: /**
2: * <防空炮>
3: */
4: public class FlakCannon
5: {
6: public FlakCannon( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的防空炮" );
9: }
10: }
1: /**
2: * <船体>
3: */
4: public class Hull
5: {
6: public Hull()
7: {
8: System.out.println( "制造了主船体" );
9: }
10: }
1: /**
2: * <导弹>
3: */
4: public class Missile
5: {
6: public Missile( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的导弹" );
9: }
10: }
1: /**
2: * <鱼雷>
3: */
4: public class Torpedo
5: {
6: public Torpedo( int no)
7: {
8: System.out.println( "制造了编号为" + no + "的鱼雷" );
9: }
10: }
再来看下船的代码,具体表示为:航母、驱逐舰、补给船:
1: /**
2: * <航母对象>
3: */
4: public class AircraftCarrier
5: {
6: //航母名称
7: private String name;
8:
9: //舰载飞机
10: private List<Aircraft> aircrafts;
11:
12: //防空炮
13: private List<FlakCannon> flakCannons;
14:
15: //船体
16: private Hull hull;
17:
18: //设备
19: private List<Equipment> equipments;
20:
21: public AircraftCarrier(String name)
22: {
23: this .name = name;
24: equipments = new ArrayList<Equipment>();
25: aircrafts = new ArrayList<Aircraft>();
26: flakCannons = new ArrayList<FlakCannon>();
27: }
28: //get/set方法忽略
29: }
1: /**
2: * <驱逐舰对象>
3: */
4: public class Destroyer
5: {
6: //驱逐舰编号
7: private String name;
8:
9: //防空炮
10: private List<FlakCannon> flakCannons;
11:
12: //船体
13: private Hull hull;
14:
15: //设备
16: private List<Equipment> equipments;
17:
18: //鱼雷
19: private List<Torpedo> torpedos;
20:
21: //导弹
22: private List<Missile> missiles;
23:
24: public Destroyer(String name)
25: {
26: this .name = name;
27: equipments = new ArrayList<Equipment>();
28: flakCannons = new ArrayList<FlakCannon>();
29: torpedos = new ArrayList<Torpedo>();
30: missiles = new ArrayList<Missile>();
31: }
32: //get/set方法省略
33: }
1: /**
2: * <补给船>
3: */
4: public class Tender
5: {
6: //补给船名称
7: private String name;
8:
9: //船体
10: private Hull hull;
11:
12: //设备
13: private List<Equipment> equipments;
14:
15: public Tender(String name)
16: {
17: this .name = name;
18: equipments = new ArrayList<Equipment>();
19: }
20:
21: //get/set方法省略
22: }
下面是生成器(Builder)的代码:
1: /**
2: * <舰船Builder>
3: */
4: public abstract class ShipBuilder
5: {
6: //建造船
7: public abstract void buildShip(String name);
8:
9: //建造船体
10: public abstract void buildHull();
11:
12: //建造设备
13: public abstract void buildEquipment( int no);
14:
15: //建造导弹
16: public abstract void buildMissile( int no);
17:
18: //建造鱼雷
19: public abstract void buildTorpedo( int no);
20:
21: //建造飞机
22: public abstract void buildAircraft( int no);
23:
24: //建造防空炮
25: public abstract void buildFlakCannon( int no);
26:
27: //返回结果
28: public abstract Object getResult();
29: }
生成器可以是抽象类也可以是接口,再来看下几个具体生成器的代码(ConcreteBuilder):
1: /**
2: * <建造航母类>
3: */
4: public class AircraftCarrierBuilder extends ShipBuilder
5: {
6: private AircraftCarrier aircraftCarrier;
7:
8: public void buildShip(String name)
9: {
10: this .aircraftCarrier = new AircraftCarrier(name);
11: }
12:
13: public AircraftCarrier getResult()
14: {
15: System.out.println( "\"" + aircraftCarrier.getName() + "\"号航母制造完成" );
16: return aircraftCarrier;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22: this .aircraftCarrier.getAircrafts().add( new Aircraft(no));
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .aircraftCarrier.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .aircraftCarrier.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .aircraftCarrier.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
1: /**
2: * <驱逐舰建造>
3: */
4: public class DestoryerBuilder extends ShipBuilder
5: {
6: private Destroyer destroyer;
7:
8: public void buildShip(String name)
9: {
10: this .destroyer = new Destroyer(name);
11: }
12:
13: public Destroyer getResult()
14: {
15: System.out.println( "\"" + destroyer.getName() + "\"号驱逐舰制造完成" );
16: return destroyer;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .destroyer.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34: this .destroyer.getFlakCannons().add( new FlakCannon(no));
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .destroyer.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46: this .destroyer.getMissiles().add( new Missile(no));
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52: this .destroyer.getTorpedos().add( new Torpedo(no));
53: }
54: }
1: /**
2: * <补给船建造类>
3: */
4: public class TenderBuilder extends ShipBuilder
5: {
6: private Tender tender;
7:
8: public void buildShip(String name)
9: {
10: this .tender = new Tender(name);
11: }
12:
13: public Tender getResult()
14: {
15: System.out.println( "\"" + tender.getName() + "\"号补给船制造完成" );
16: return tender;
17: }
18:
19: @Override
20: public void buildAircraft( int no)
21: {
22:
23: }
24:
25: @Override
26: public void buildEquipment( int no)
27: {
28: this .tender.getEquipments().add( new Equipment(no));
29: }
30:
31: @Override
32: public void buildFlakCannon( int no)
33: {
34:
35: }
36:
37: @Override
38: public void buildHull()
39: {
40: this .tender.setHull( new Hull());
41: }
42:
43: @Override
44: public void buildMissile( int no)
45: {
46:
47: }
48:
49: @Override
50: public void buildTorpedo( int no)
51: {
52:
53: }
54: }
大家也许注意到了,3个具体生成器中存在空方法,比如在航母生成器中的buildMissile和buildTorpedo,因为我们定义的在航母上没有导弹和鱼雷。
GOF在设计模式中举的例子是用C写的,生成器父类里使用了虚函数,有点像java的abstract,在具体生成器子类中可以选择性的重写父类方法,但是java中没有虚函数,所以只能采用接口或者抽象类,那么在子类中必须实现所有的方法,所以我只能给空的实现了。
再来看一下导向器的代码,在导向器中要对Builder进行配置,并如前面结构图中所画的,在导向器中定义了各种构造的算法:
1: /**
2: * Director
4: */
5: public class ShipFactory
6: {
7: private ShipBuilder shipBuilder;
8:
9: public ShipFactory(ShipBuilder shipBuilder)
10: {
11: this .shipBuilder = shipBuilder;
12: }
13:
14: public void createShip( int shipType, String name)
15: {
16: shipBuilder.buildShip(name);
17: shipBuilder.buildHull();
18: switch (shipType)
19: {
20: //中国航母
21: case 1:
22: buildAircraftCarrierCHN();
23: break ;
24: //外国航母
25: case 2:
26: buildAircraftCarrierUSA();
27: break ;
28: //驱逐舰
29: case 3:
30: buildDrstroyer();
31: break ;
32: //补给船
33: case 4:
34: buildTender();
35: break ;
36: }
37: }
38:
39: private void buildAircraftCarrierCHN()
40: {
41: for ( int i=1; i<6; i++)
42: {
43: shipBuilder.buildEquipment(i);
44: }
45: for ( int i=1; i<11; i++)
46: {
47: shipBuilder.buildAircraft(i);
48: }
49: for ( int i=1; i<11; i++)
50: {
51: shipBuilder.buildFlakCannon(i);
52: }
53: }
54:
55: private void buildAircraftCarrierUSA()
56: {
57: for ( int i=1; i<7; i++)
58: {
59: shipBuilder.buildEquipment(i);
60: }
61: for ( int i=1; i<12; i++)
62: {
63: shipBuilder.buildAircraft(i);
64: }
65: for ( int i=1; i<12; i++)
66: {
67: shipBuilder.buildFlakCannon(i);
68: }
69: }
70:
71: private void buildTender()
72: {
73: for ( int i=1; i<6; i++)
74: {
75: shipBuilder.buildEquipment(i);
76: }
77: }
78:
79: private void buildDrstroyer()
80: {
81: for ( int i=1; i<6; i++)
82: {
83: shipBuilder.buildEquipment(i);
84: }
85: for ( int i=1; i<12; i++)
86: {
87: shipBuilder.buildMissile(i);
88: }
89: for ( int i=1; i<12; i++)
90: {
91: shipBuilder.buildFlakCannon(i);
92: }
93: for ( int i=1; i<12; i++)
94: {
95: shipBuilder.buildTorpedo(i);
96: }
97: }
98: }
最后看下使用的代码:
1: public class Client
2: {
3: public static void main(String[] args)
4: {
5: ShipBuilder builder = new AircraftCarrierBuilder();
6: // ShipBuilder builder = new DestoryerBuilder();
7: // ShipBuilder builder = new TenderBuilder();
8: ShipFactory factory = new ShipFactory(builder);
9: factory.createShip(1, "和谐" );
10: // factory.createShip(2, "圣母玛利亚");
11: // factory.createShip(3, "牛逼号");
12: // factory.createShip(4, "龙套号");
13: builder.getResult();
14: }
15: }
运行结果:
1: 制造了主船体
2: 制造了编号为1的设备
3: 制造了编号为2的设备
4: 制造了编号为3的设备
5: 制造了编号为4的设备
6: 制造了编号为5的设备
7: 生产了编号为1的战斗机
8: 生产了编号为2的战斗机
9: 生产了编号为3的战斗机
10: 生产了编号为4的战斗机
11: 生产了编号为5的战斗机
12: 生产了编号为6的战斗机
13: 生产了编号为7的战斗机
14: 生产了编号为8的战斗机
15: 生产了编号为9的战斗机
16: 生产了编号为10的战斗机
17: 制造了编号为1的防空炮
18: 制造了编号为2的防空炮
19: 制造了编号为3的防空炮
20: 制造了编号为4的防空炮
21: 制造了编号为5的防空炮
22: 制造了编号为6的防空炮
23: 制造了编号为7的防空炮
24: 制造了编号为8的防空炮
25: 制造了编号为9的防空炮
26: 制造了编号为10的防空炮
27: "和谐" 号航母制造完成
至此代码示例就结束了。
一些思考(1)产品(Product)需不需要抽象类?
GOF给出了答案: 通常情况下,由具体生成器生成的产品,它们的表示相差是如此之大以至于给不同的产品以公共父类没有太大意思。
上面船的例子可能不太贴切,毕竟船之间会有公共的东西,但是换个其他的例子比如构造一副画,不同的画之间很难有共同之处,所以给它们公共接口是没有意义的,它们也不需要这样的接口。因为客户通常用合适的具体生成器来配置导向器,客户的位置使得它很容易的就知道Builder的哪个具体子类被使用和能相应的处理它的产品
(2)多重Builder?
在写上面的例子的时候我是颇有些疑问的,船是由船体、设备、武器等构造出来的,而船体、设备、武器等也是由其他级别更低的组件构造的,它们之间也存在着复杂的构造关系。这中间可能有好几层,知道追溯到螺丝、螺母这样的原子级零件,每一层复杂的构造关系都可以用Builder模式表示。而往上,多艘船可以构造成一个舰队;多个舰队构造成海军等等。
于是我陷入了疑惑,这样多层的Builder模式我该如何表示?直到我看到了一句话: Composite模式通常是由Builder生成的 。原来这样多重的Builder关系已经属于另外一种模式了,那么就论Builder模式的话,我们只需要关注其中的一层构造过程就可以了。
关于Builder模式就这么多了,虽然这个模式好像并不经常用。自己理解了Builder模式有一段时间,自觉理解的并不透彻,有些地方还是生搬硬套,也没有实际运用的场景和经验,有一些思考,有一些疑问,希望大家补全,互相学习。
我只是走在路上,偶尔驻足观赏,偶尔回头看看。
分类: 设计模式 , Java相关
http://www.cnblogs.com/tjcjxy/archive/2010/10/31/1865626.html
12 2010 档案
代理模式
摘要: 一、完成者信息:姓名:杨郅昱学号:07770121二、模式信息模式名称:代理模式生活场景:判定是否是三角形然后求出面积:任意给定三个数,先判断是否能构成三角形 如果能构成三角形,在求出三角形的面积。1.不假思索的思路:通过类继承的方式来做上面的例子。即:任意给定三个数字, 用一个类继承运算接口,先判定能否构成三角形,如果能,求出面积;如果不能,则停止运行。2.类结构图:代码浏览:代码1. 存在问题:1. 当调入大量信息时会发费很长时间。2. 进行判定和计算都在一个类中进行,需要大量的时间。3. 如果判定规则变动,则需要大量的修改。2.归纳阶段归纳步骤一当前目标:实现通过一个代理来处理请求,并将 阅读全文
posted @ 2010-12-16 15:15 天津城建学院软件工程 阅读(46) | 评论 (0) 编辑
桥接模式
摘要: 姓名:陈阳学号:07770114一、模式信息模式名称:桥接模式生活场景:考虑一个售楼小区不同的建筑面积、不同楼层的每平米造价成本是不同的。同一建筑面积的屋子,有楼层的高低之分。而同一楼层也会有建筑面积不一样的屋子终极目标:实现适应于扩充到对各种建筑面积的屋子和各种楼层进行建模的情形。1.不假思索的思路:通过类继承的方式来做上面的例子。即:先建立楼层类;然后派生出高楼层类、矮楼层类;然后再高楼层类和矮楼层类上分别派生出:大面积房屋类和小面积房屋类。类结构图:代码浏览:代码存在问题:1.它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有 阅读全文
posted @ 2010-12-15 17:12 天津城建学院软件工程 阅读(20) | 评论 (0) 编辑
迭代器模式
摘要: 一、完成者信息:姓名: 王延学号:07770125二、模式信息模式名称:迭代器生活场景:将保险柜里的钱分类,从中选出假币。终极目标:合计最终真币的总数。 1.不假思索的思路:通过类和类之间参数的调用来实现最后结果。类结构图:代码浏览:代码:存在问题:1.计算过程过于复杂。2.类Real的实用性很差,可以直接去掉。3.继承和调用的次数过多,容易混乱。4.new的对象名过多,容易混搅。2.归纳阶段归纳步骤一、二、四当前目标:实现假币的计算和最后的总和思路:类结构图:代码浏览:代码:设计体会:节省了很多不必要的步骤,是过程简明了很多。减少了出错的可能性,是程序的耦合程度大大减少。 验证结论:用户使用 阅读全文
posted @ 2010-12-15 16:46 天津城建学院软件工程 阅读(16) | 评论 (0) 编辑
享元模式
摘要: 一、完成者信息:姓名:王智超学号:07770120二、模式信息模式名称:享元模式生活场景:考虑生产汽车的场景:一个品牌有各种型号的汽车,每种型号的汽车有相同的参数(如型号,长,宽,高),也有不同的参数(如颜色,马力) ,就可以把相同的参数拿出来共享。终极目标:实现适应于扩充到对各种汽车和各种型号进行建模的情形。1.不假思索的思路:通过给属性赋值的方法来做:没一辆车都有自己的所有的参数的属性。 类结构图: 代码浏览:代码实现:客户端调用: 存在问题: 1.重复代码会很多,相同的型号汽车有一部分参数是相同的; 2.类的结构过于复杂,难于维护; 3.最致命的一点是效率太差。生产大量汽车会创 阅读全文
posted @ 2010-12-15 16:18 天津城建学院软件工程 阅读(41) | 评论 (0) 编辑
装饰模式
摘要: 一、完成者信息:姓名:张璐璐学号:07770232二、模式信息模式名称:装饰模式生活场景:加工蛋糕的场景:现有烤好的蛋糕,接下来我们要给蛋糕切好形状,然后涂上奶油或巧克力,再放上草莓,最后插上蜡烛。1.不假思索的思路: 按类继承的作法如下:类图:代码存在问题:由此可见,如果用类继承实现,子类会爆炸式地增长。动机(Motivate):上述描述的问题根源在于我们“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态物质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能组合)会导致更多子类的膨胀(多继承)。2.归纳阶段如何使“对象功能的扩展”能够根据 阅读全文
posted @ 2010-12-15 15:45 天津城建学院软件工程 阅读(38) | 评论 (1) 编辑
模板方法模式
摘要: 一、完成者信息姓名:陈绯学号:07770230二、模式信息模式名称:模板方法模式1.问题描述生活场景:大家都经常会用到对数据库中表进行操作,有时候数据库中有若干个表,我们往往是一个一个的对相应的表进行连接数据库,然后对指定的表进行增、删、改、查的一系列操作,组后关闭数据库的连接。但是当我们要对大型的数据库进行这些操作的时候,你会发现这些操作很繁琐,要对每一个表都进行相同的处理,加大的数据的操作工作。设计目的:实现对若干个不相同的表进行重复的增删改查工作。2.不假思索的思路思路描述:对TemplateMethod数据库中的Categories表进行数据库的连接,表的增删改查以及数据库的关闭等操作 阅读全文
posted @ 2010-12-09 16:52 天津城建学院软件工程 阅读(325) | 评论 (0) 编辑
访问者模式
摘要: 一、完成者信息:姓名:王璐学号:07770231二、模式信息模式名称:访问者模式生活场景:假如以前食堂的食品和饮料一直都是一个价位,没有变动。这学期开学,由于工商局调节价位,导致普遍商品都涨价了,所以学校食堂里,菜价和饮料都涨价了。终极目标:实现能够对所有的情况进行访问,通知发生变化。不使用访问者模式不假思索的思路:我们去吃饭,首先看菜单,来选择食物,用现在的菜单跟以前的菜单相对比,价位之间的变化。类结构图:代码实现:代码运行结果:存在问题:在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的改变,将会给子类带来很繁重的变更负担,甚至破坏原有 阅读全文
posted @ 2010-12-09 13:07 天津城建学院软件工程 阅读(135) | 评论 (0) 编辑
装饰模式
摘要: 姓名:高振松学号:077701161、生活场景:看过美国科幻片的同学应该都会为美国人那惊人的想象力说折服吧。在美国的科幻片里有一种东西会经常在镜头里出现,那就是会飞行的交通工具(汽车,卡车之类的)。这些交通工具既可以在陆地上跑,也可以在天空中飞行或者在水中行驶。现假设,现在有一家汽车生产商,最近突破一项关键技术,使得所有类型的车辆都可以在天空中飞或者在水中行驶的功能。而你正好在给该生产商开发系统软... 阅读全文
posted @ 2010-12-01 21:49 天津城建学院软件工程 阅读(155) | 评论 (0) 编辑
代理模式
摘要: 姓名:宁前程学号:07770118模式名称:代理模式1.问题描述生活场景:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买,不但买不到自己想要的衣服,还白白的跑了一趟。设计目的:让用户不必非要跑到李宁公司总部去购买。2.不假思索的思路思路描述:很多人想购买李宁牌衣服,然后纷纷跑到李宁公司总部去购买。类结构图:缺点:这样的设计,为公司造成很多麻烦,也为自己造成很多麻烦。代码:首先定义一个能产生... 阅读全文
posted @ 2010-12-01 21:28 天津城建学院软件工程 阅读(45) | 评论 (0) 编辑
11 2010 档案
闲谈责任链模式
摘要: 责任链模式是使用多个对象处理用户请求的成熟模式,责任链模式的关键是将用户的请求分派给许多对象,这些对象被组织成一个责任链,即每个对象含有后继对象的引用,并要求责任链上的每个对象,如果能处理用户的请求,就做出处理,不再将用户的请求传递给责任链上的下一个对象,如果不能处理用户的请求,就必须将用户的请求传递给责任链上的下一个对象。 阅读全文
posted @ 2010-11-30 23:59 天津城建学院软件工程 阅读(183) | 评论 (0) 编辑
生产器模式
摘要: 作者:苏石 07770107模式名称生产器模式模式介绍生成器(Builder)模式,也被称为建造者模式或构造器模式,属于创建型模式,它是将一个复杂的对象的构造与这个复杂对象的表示分离开 ,使得同样的构建构成可以创建不同的表示。问题提出生活场景:仍以生产洗发水为例,原生产的洗发水只有一种类型,比如:功效是去屑,包装都是一样的。但随着科技的发展、消费水平的提升,只生产这种单一类型的洗发水已经不能满足当... 阅读全文
posted @ 2010-11-30 17:02 天津城建学院软件工程 阅读(116) | 评论 (0) 编辑
Template Method Pattern 模版方法模式
摘要: Template MethodPattern作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的模版方法模式。 问题:现在有一家汽车生产商需要一个管理汽车生产的管理软件。其中在该系统中有一个管理组装汽车的子模块。该模块要能根据不同的汽车类型来组装相应的汽车。汽车的被组装部分分别是汽车的车盖,车地盘,后备箱,车胎。现在来试着实现下该过程。 根据上面的描述,我在这里选择里... 阅读全文
posted @ 2010-11-28 16:15 天津城建学院软件工程 阅读(240) | 评论 (2) 编辑
生成器模式(又名建造者模式、Builder Pattern)
摘要: 姓名:谭鹏飞学号:07770106模式名称:生成器模式1.问题描述生活场景:你玩过种地、种花等类似的游戏吗?这是最近很流行的游戏哟!下面就是从种花游戏中剪切的四个花盆(盆景),很漂亮吧!你将不同的种子放入花盆,一段时间后你就可以看到各种美丽的鲜花了,不同种子所生产出来的鲜花有不同的花朵、叶子和枝茎。编码该如何实现呢? 设计目标:将种子放入花盆,一段时间后就可以收获美丽的鲜花!2.不假思索的思路:将... 阅读全文
posted @ 2010-11-26 12:50 天津城建学院软件工程 阅读(1256) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息姓名:周智学号:07770108二、模式名称适配器模式三、模式介绍定义:在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。分类:对象适配器模式 - 在这种适配器模式中,适配器容纳一个它我包裹的类的实例。在这种情况下,适配器调用被包裹对象的物... 阅读全文
posted @ 2010-11-25 16:21 天津城建学院软件工程 阅读(127) | 评论 (0) 编辑
工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:工厂模式模式概述: 当系统准备为用户提供某个类的子类的实例,又不想让用户代码和该子类形成耦合时,就可以使用工厂方法模式来设计系统。工厂方法模式的关键是在一个接口或抽象类中定义一个抽象方法,该方法返回某个类的子类实例,该抽象类或接口让其子类或实现该接口的类通过重写这个抽象方法返回某个子类的实例。工厂方法模式的结构中包括四种角色。●... 阅读全文
posted @ 2010-11-21 22:31 天津城建学院软件工程 阅读(49) | 评论 (0) 编辑
简单工厂模式04
摘要: 一、完成者信息:姓名:韦庆学号:07770104二、模式信息模式名称:简单工厂模式模式概述: 简单工厂模式的实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品类的实例。简单工厂模式涉及到工厂角色、抽象产品角色和具体产品角色三个参与者。● 工厂(Creator)角色是简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。● 抽象产品(Prod... 阅读全文
posted @ 2010-11-21 21:01 天津城建学院软件工程 阅读(55) | 评论 (0) 编辑
桥接模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:桥接模式2、模式概述: Bridge桥接模式是一种结构型模式,它主要应对的是:由于类型的固有罗辑,使得类型具有两个或两个以上的纬度变化。也就是要求抽象不应依赖于实现细节,实现细节应依赖于抽象。桥接模式包括四种角色。● 抽象(Abstraction):是一个抽象类,该抽象类含有Implementor声明的变量,即维护一个Im... 阅读全文
posted @ 2010-11-21 18:57 天津城建学院软件工程 阅读(59) | 评论 (1) 编辑
适配器模式
摘要: 一、完成者信息:姓名:赖春林学号:07770110二、模式信息1、模式名称:适配器模式2、模式概述: 在现实生活中往往会遇到这样的问题:很多设备需要使用同一种资源,但每一种设备使用这种资源时都需要特定的接口,这些接口都不一样。现在的问题是怎样实现在没有对应接口的情况下也使设备能够使用呢?这时就可以用到适配器模式。3、定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接... 阅读全文
posted @ 2010-11-21 18:52 天津城建学院软件工程 阅读(118) | 评论 (0) 编辑
原型模式
摘要: 一、完成者信息姓名:赖春林学号:07770110二、模式信息1、模式名称:原型模式2、模式概述: 在软件系统中,有时候面临的产品类是动态变化的,而且这个产品类具有一定的等级结构。这时如果用工厂模式,则与产品类等级结构平行的工厂方法类也要随着这种变化而变化,显然不大合适。那么如何封装这种动态的变化?从而使依赖于这些易变对象的客户程序不随着产品类变化?3、定义:用原型实例指定创建对象的种类,并且通过拷... 阅读全文
posted @ 2010-11-21 18:36 天津城建学院软件工程 阅读(78) | 评论 (2) 编辑
观察者模式
摘要: 一、完成者信息:姓名:周义学号:07770207二、模式信息模式名称:观察者模式模式概述: 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依... 阅读全文
posted @ 2010-11-21 17:10 天津城建学院软件工程 阅读(134) | 评论 (0) 编辑
访问者模式 Visitor Pattern
摘要: 访问者模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的访问者模式。 在介绍访问者模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:有一天,有两个不同公司的业务员来到两家相同的公司进行业务商讨。两个业务员对同一个公司的业务不相同。试着编程实现给过程。 倘若您作为编写者,一般情况下您会如何来处理这个问题 我在这里展示我的不假思索的解决方... 阅读全文
posted @ 2010-11-01 12:28 天津城建学院软件工程 阅读(94) | 评论 (0) 编辑
10 2010 档案
策略模式
摘要: 策略模式 作者:崔涛涛(07770225) 今天我要在这里介绍的是C#设计模式中的策略模式。 介绍策略模式之前,我们先在这里看个我虚构与今天我要讲解的模式有关的简短的问题。问题:如今网购盛行,很多人都应该在网上买过东西,虚拟物品或者是非虚拟物品。在B2C的网络购物网站中,商家为了吸引买家常会推出比较优惠的折扣。现在有家B2C的购物网站,它的折扣方式是这样的,对于VIP来说基本的折扣率是20%... 阅读全文
posted @ 2010-10-31 16:32 天津城建学院软件工程 阅读(199) | 评论 (0) 编辑
适配器模式
摘要: 姓名:赵汉青学号:07770201模式名称:适配器模式1.问题描述生活场景:日常生活中,我们所使用的电器,比如:手机,笔记本电脑,剃须刀等在充电时所需要的电压,均不是我国提供的统一民用电压“220v”,而我们又只能使用已经存在的电压给电器充电,这时,就需要一个电源适配,把220V的电压转化为电器所需的电压值。设计目标:实现对不能满足新化境的“已存对象&rdquo... 阅读全文
posted @ 2010-10-26 00:07 天津城建学院软件工程 阅读(178) | 评论 (2) 编辑
抽象工厂模式
摘要: 姓名:赵汉青学号:07770201模式名称:抽象工厂模式1.问题描述生活场景:某家具厂为学校生产课桌和座椅,开始只生产木质的课桌和座椅,后来经学校要求,又开始为学校生产铁质的课桌和座椅。设计目标:实现针对多种成套产品的生产,每套产品有多种不同等级结构的物品组成。2.不假思索的思路思路描述:通过简单工厂的模式来实现。即在生产木质课桌的工厂里加开生产铁质课桌的生产线;在生产木质椅子的工厂里加开生产铁质... 阅读全文
posted @ 2010-10-21 23:24 天津城建学院软件工程 阅读(151) | 评论 (1) 编辑
工厂方法模式
摘要: 姓名:赵汉青学号:07770201模式名称:工厂方法模式1.问题描述生活场景:很多的公司都通过生产不同品牌的同一类产品来占有市场,比如,联合利华公司生产洗发水,开始只有“夏士莲”系列,后来为了在洗发水市场上扩充份额,又推出了“清扬”系列。你会发现,不管是“清扬”还是“夏士莲”,有着相同的功能&mdash... 阅读全文
posted @ 2010-10-21 23:13 天津城建学院软件工程 阅读(475) | 评论 (0) 编辑
test
摘要: test 阅读全文
posted @ 2010-10-11 15:49 天津城建学院软件工程 阅读(21) | 评论 (0) 编辑
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息