- 浏览: 12566 次
- 性别:
- 来自: 大连
最近访客 更多访客>>
文章分类
最新评论
-
weishuguangeye:
写的非常好,总结的也非常好!感谢!
初学Java设计模式随记 -- 抽象工厂(Abstract Factory)模式
建造者(BUILDER)模式又叫生成器(BUILDER)模式。它的定义如下:(参见GoF的设计模式与阎宏的《Java与模式》)
1. 用意:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2. 参与者:
• 抽象建造者(Builder): 为创建一个产品(Prodcut)对象的各个部件指定抽象接口。
• 具体建造者(ConcretBuilder):
实现抽象建造者(Builder)的接口以构造和装配该产品的各个部件。
定义并明确它所创建的表示。
提供一个检索产品的接口。
• 导演者(Director):构造一个使用抽象建造者(Builder)接口的对象。
• 产品(Prodcut):
表示被构造的复杂对象。具体建造者(ConcretBuilder)创建该产品的内部表示并定义它的装配过程。
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
3. 结构:
根据GoF的设计模式,来描述一下建造者(BUILDER)模式使用时,各个角色之间的协作关系:
1. 客户创建导演者(Director)对象,并用它所想要的抽象建造者(Builder)的一个具体建造者(ConcretBuilder)对象进行配置。
2. 当产品的某个部件(PartOne, PartTwo, ...)需要被创建时,导演者(Director)就会通知具体建造者(ConcretBuilder)。
3. 具体建造者(ConcretBuilder)处理导演者(Director)的请求,并将部件(PartOne, PartTwo, ...)添加到该产品(Prodcut)中。
4. 客户从具体建造者(ConcretBuilder)中检索产品(Prodcut)。
===============小插曲===============================
在参看《设计模式可复用面向对象软件的基础》(GOF设计模式中文版)时,对于Builder模式中协作的第二条描述,无法理解:
一旦产品部件被生成,导向器就会通知生成器。(查看维基百科中文,也是这么翻译的)
对比英文原著,是这样描述的:
Director notifies the builder whenever a part of the product should be built.
那么,是不是应该翻译成下面的意思呢?
当产品的某个部件需要(应当)被创建的时候,导向器就会通知生成器。
(或者说,一旦产品部件需要被生成,导向器就会通知生成器。)
这里,可能有点较真了,不过,个人觉得,前后两种中文表达的应该是不同的含义。
=====================================================
根据现实的例子,来理解建造者模式。还是用生产汽车来举例。例子9
顾客想购买一辆一汽大众的汽车。
汽车实际就是一个产品族,即一套(一系列)汽车零部件产品(产品族)组合。
汽车的构造可是非常复杂的。它要有轮子,方向盘,座椅,发动机,颜色等等。
怎么这个例子看起来这么熟悉?
1. 好像与前一篇随记初学Java设计模式随记 -- 抽象工厂(Abstract Factory)模式很相似:
它们都可以创建复杂对象(产品集合或产品族)。
在GoF的设计模式中是这么说的:
Abstract Factory与Builder相似,因为它也可以创建复杂对象。主要的区别是Builder模式着重于一步步构造一个复杂对象。而Abstract Factory着重于多个系列的产品对象(简单的或是复杂的)。
也就是说,Builder模式关心的是怎样把复杂的产品的各个部件(或部件产品)给组装起来;
而Abstract Factory模式关心的是把哪些部件(或部件产品)给组装起来。
2. 好像与之前的另一篇随记初学Java设计模式随记 -- 工厂模式(Factory Pattern)也很相似:
回顾工厂模式的优势,与建造者模式的用意比较一下:
利用工厂模式可以将对象的创建过程和使用进行分离(也就是解藕)。
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
个人觉得,
建造者模式更侧重于有规则或有序的创建(构建)过程;
而工厂模式的创建(构建)过程比较随意。
其实,也可以从工厂和建造者这两个名字来体会他们的差异:
建造者更像是工厂里的生产设备。
工厂只关心生产什么产品,他只知道这个产品是由什么组成的;
建造者需要考虑怎么生产产品,他需要考虑产品的组成规则和方法。
或者说,在某种程度上,建造者模式就好像把工厂模式中工厂角色的一些职责工作内容,给做了一些细化。
由导演者(Director)指导产品的生产,由建造者实施具体的生产。
继续这个例子,来体会建造者模式:
抽象建造者:
/* * 建造者 */ public interface CarBuilder { /** * 建造汽车的框架 */ public void buildeCarSkeleton(); /** * 给汽车装上发动机 */ public void buildeCarEngine(); /** * 给汽车装上轮子 */ public void buildeCarWheels(); /** * 给汽车装上导航设备 */ public void buildeCarNavigation(); /** * 安装车身(包含车门、车窗的安装,涂颜色) */ public void buildeCarBody(); }
具体建造者:(生产奥迪A6)
导演者:
这里,由导演者指导建造者以一定的方式生产汽车(安装了导航系统)
/* * 导演者 */ public class AudiDirector { CarBuilder builder; /** * 为导演者配置一个建造者 */ public AudiDirector(CarBuilder builder){ this.builder = builder; } /** * 按照一定的方式或规则建造汽车 */ public void contruct(){ builder.buildeCarSkeleton(); builder.buildeCarEngine(); builder.buildeCarNavigation(); builder.buildeCarWheels(); builder.buildeCarBody(); } }
奥迪汽车(产品):
/* * 产品 */ public class AudiCar { private String carSkeleton; private Engine carEngine; private String carWheels; private String carNavigation = ""; private String carDoor; private String carWindscreen; private String carColor; public AudiCar(){ } /** * 汽车的颜色 */ public void setCarColor(String carColor) { this.carColor = carColor; } /** * 汽车的车门 */ public void setCarDoor(String carDoor) { this.carDoor = carDoor; } /** * 汽车发动机,发动机在这里是一个对象 */ public void setCarEngine(Engine carEngine) { this.carEngine = carEngine; } /** * 汽车的框架 */ public void setCarSkeleton(String carSkeleton) { this.carSkeleton = carSkeleton; } /** * 汽车轮子 */ public void setCarWheels(String carWheels) { this.carWheels = carWheels; } /** * 汽车的挡风玻璃 */ public void setCarWindscreen(String carWindscreen) { this.carWindscreen = carWindscreen; } /** * 汽车导航 */ public void setNavigation(String navigation) { this.carNavigation = navigation; } /** * 一个汽车对象的描述 */ public String toString(){ return carSkeleton+ "," + carEngine.toString() +"," + carWheels + "," + carDoor + "," + carWindscreen + "," + carColor + "," + carNavigation; } }
汽车的一个部件对象:
/* * 一个部件对象(汽车发动机) */ public class Engine { private String name; public Engine(String name){ this.name = name; } public String toString(){ return this.name; } }
客户端:
/* * 客户端 */ public class Clients { public static void main(String[] args) { // 创建一个建造者对象 AudiCarBuilder builder = new AudiCarBuilder(); // 创建一个导演者,并为它配置一个建造者 AudiDirector director1 = new AudiDirector(builder); // 导演者将通知建造者去创建产品 // 在这个过程中,建造者将会根据导演者的请求,去创建组织并创建产品对象 director1.contruct(); // 从具体建造者中检索产品(返回的是带导航的汽车产品)。 AudiCar audiCar = builder.retrieveCar(); System.out.println(audiCar); } }
运行结果:
汽车框架,奥迪A6发动机,车轮,车门,挡风玻璃,黑色,汽车导航
如果想生产一款没有导航系统的奥迪A6汽车,怎么实现呢?
只需要修改一下导演者就可以了。
新的导演者:(指示建造者不安装导航系统)
/* * 导演者 */ public class AudiDirector { CarBuilder builder; /** * 为导演者配置一个建造者 */ public AudiDirector(CarBuilder builder){ this.builder = builder; } /** * 按照一定的方式或规则建造汽车 */ public void contruct(){ builder.buildeCarSkeleton(); builder.buildeCarEngine(); // 不安装导航系统 // builder.buildeCarNavigation(); builder.buildeCarWheels(); builder.buildeCarBody(); } }
运行结果:(没有导航系统)
汽车框架,奥迪A6发动机,车轮,车门,挡风玻璃,黑色,
如果想生产奥迪A8且带导航系统的汽车,怎么实现呢?
(假设奥迪A6与奥迪A8的差别只是发动机)
只需要修改建造者类就可以了。
建造者:(只是改变自己的内部实现--把奥迪A6发动机改为奥迪A8发动机)
/*
* 具体建造者
*/
public class AudiCarBuilder implements CarBuilder {
private AudiCar audiCar = new AudiCar();
/**
* 安装车身(包含车门、车窗的安装,涂颜色)
*/
public void buildeCarBody() {
audiCar.setCarDoor("车门");
audiCar.setCarWindscreen("挡风玻璃");
audiCar.setCarColor("黑色");
}
/**
* 给汽车装上发动机
*/
public void buildeCarEngine() {
Engine audiEngine = new Engine("奥迪A8发动机");
audiCar.setCarEngine(audiEngine);
}
/**
* 给汽车装上导航设备
*/
public void buildeCarNavigation() {
audiCar.setNavigation("汽车导航");
}
/**
* 建造汽车的框架
*/
public void buildeCarSkeleton() {
audiCar.setCarSkeleton("汽车框架");
}
/**
* 给汽车装上轮子
*/
public void buildeCarWheels() {
audiCar.setCarWheels("车轮");
}
public AudiCar retrieveCar(){
return audiCar;
}
}
运行结果:(更换成了奥迪A8发动机)
汽车框架,奥迪A8发动机,车轮,车门,挡风玻璃,黑色,汽车导航
从这个例子就可以看出,建造者模式的优势:
1. 导演者可以指定不同的生产方式(是否安装导航),而建造者不需要做任何改变,就可以得到不同的产品
2. 导演者不需要改变期望的生产方式,只需要建造者改变自己的内部实现(选择什么型号的发动机),也可以得到不同的产品。
关于建造者模式带来的效果,参看GoF的《设计模式》。
/* * 具体建造者 */ public class AudiCarBuilder implements CarBuilder { private AudiCar audiCar = new AudiCar(); /** * 安装车身(包含车门、车窗的安装,涂颜色) */ public void buildeCarBody() { audiCar.setCarDoor("车门"); audiCar.setCarWindscreen("挡风玻璃"); audiCar.setCarColor("黑色"); } /** * 给汽车装上发动机 */ public void buildeCarEngine() { Engine audiEngine = new Engine("奥迪A6发动机"); audiCar.setCarEngine(audiEngine); } /** * 给汽车装上导航设备 */ public void buildeCarNavigation() { audiCar.setNavigation("汽车导航"); } /** * 建造汽车的框架 */ public void buildeCarSkeleton() { audiCar.setCarSkeleton("汽车框架"); } /** * 给汽车装上轮子 */ public void buildeCarWheels() { audiCar.setCarWheels("车轮"); } public AudiCar retrieveCar(){ return audiCar; } }
发表评论
-
初学Java设计模式随记 -- 适配器(Adpater)模式
2011-01-10 10:10 0适配器(Adpater)模式 1.用意: 将一个类的 ... -
初学Java设计模式随记 -- 装饰(Decorator)模式
2011-01-06 21:32 978装饰(Decorator)模式又叫包装器(Wrapper)模式 ... -
初学Java设计模式随记 -- 代理(Proxy)模式之动态代理(Dynamic Proxy)
2010-12-28 20:51 950什么是动态代理? 被代理的对象(真实主题(RealSu ... -
初学Java设计模式随记 -- 代理(Proxy)模式之静态代理(Static Proxy)
2010-12-28 20:51 885代理(Proxy)模式 1. 用意:为其他对象提供一种 ... -
初学Java设计模式随记 -- 原型(Prototype)模式
2010-12-11 16:44 929原型(Prototype)模式也有 ... -
初学Java设计模式随记 -- 单例(Singleton)模式
2010-12-01 22:19 739本篇内容主要摘取自GoF的设计模式和阎宏的《Java与模式》 ... -
初学Java设计模式随记 -- 抽象工厂(Abstract Factory)模式
2010-11-20 22:44 1138抽象工厂(Abstract Factory ... -
初学Java设计模式随记 -- 工厂方法(Factory Method)模式
2010-11-17 23:32 853工厂方法(Factory Method)模式,又叫做虚拟构造子 ... -
初学Java设计模式随记 -- 简单工厂模式(Simple Factory Pattern)
2010-11-17 23:32 1198简单工厂(Simple Factory)模式: 又称静态工厂方 ... -
初学Java设计模式随记 -- 工厂模式(Factory Pattern) 续
2010-11-14 21:03 848利用工厂模式可以将对象的创建过程和使用进行分离(也就是解藕), ... -
初学Java设计模式随记 -- 工厂模式(Factory Pattern)
2010-11-10 13:13 882在阎宏《JAVA与设计 ... -
初学Java设计模式随记 -- GOF 设计模式分类
2010-11-05 09:42 815以下摘自《GOF设计模式 可复用面向对象软件的基础》中文 ... -
初学Java设计模式随记 -- 带着疑问学习设计模式
2010-11-04 00:07 875最近在学习设计模式时,发现总是会有一些疑问,有的能找到答案,有 ... -
初学Java设计模式随记 -- 为什么学习设计模式
2010-11-03 21:26 697这段时间在学习设计模 ...
相关推荐
NULL 博文链接:https://andycbluo.iteye.com/blog/2269582
NULL 博文链接:https://chris-rock-f0.iteye.com/blog/1155094
Java.util包常用接口
java随记
NULL 博文链接:https://tj007-bo.iteye.com/blog/253650
OleDbDataAdapter 不会自动生成,为了使对 DataSet 所作的更改和相关联的数据源协调起来所必须的 SQL 语句。但是,如果设置了 OleDbDataAdapter 的 SelectCommand 属性,那么就可以创建 OleDbCommandBuilder 对象,来...
JSP PDF打印 随记 复杂模板设计
数据分级存储及访问方式设计方案研究随记.docx数据分级存储及访问方式设计方案研究随记.docx
一款很好用的java反编译软件,直接下载就可以使用,无需安装软件
soapUI是一个开源测试工具,通过...该工具既可作为一个单独的测试软件使用,也可利用插件集成到Eclipse,maven2.X,Netbeans 和intellij中使用。soapUI pro是soapUI的商业非开源版本,实现的功能较开源的soapUI更多。
c# 随记.docx
NULL 博文链接:https://lobin.iteye.com/blog/2365756
用户信息手账信息 第一章 用户信息信息设计 2 用户信息信息设计昵称限制:1~18位(非必需、如果没有输入则自动生成一个随机字符串6~12位、特殊符号非法)
网络原理随记.pdf
互联网公司实习日记随记参考.pdf互联网公司实习日记随记参考.pdf互联网公司实习日记随记参考.pdf互联网公司实习日记随记参考.pdf互联网公司实习日记随记参考.pdf互联网公司实习日记随记参考.pdf
linux net 管理随记,留着个人备忘
三天不读书&智商输给猪-世界读书日ppt随记PPT模板.pptx
学习c++过程中的一些知识点随记,我感觉重要的就稍微记了一下,比较简略,但是快速的阅读的话可以提醒自己想起那一部分的知识点。在复习c++知识点的时候,有些帮助。
HL_Letter个人随记
Unity 随记1