在上篇文章中,对Java Builder模式的使用体验主要是从Builder对构造器改造方面的优秀特性来说的,感觉并没有从Java Builder模式本身的功能和作用去写,因此决定再从Builder模式的作用以及在项目开发中的使用来体验下。
Builder 模式,即建造者模式,顾名思义,这个模式可能更多的使用在产品的组装中使用,具体说就是在软件产品的组件或模块组装的时候使用。
感觉网络上比较好的解释有:
[b]建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。[/b]
[b]适用的场景:[/b]
1、当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2、当构造过程必须允许被构造的对象有不同的表示时。
首先我们来说下,建造者模式中三个重要的角色:
1、Product (生产者):该角色其实类似于工厂里的流水线,它可以生产各种各样的组件,但是并不知道怎样将这些组件进行组装,进而产生出不同的产品。
2、Builder(建造者):该角色类似流水线上的操作工人,它负责将不同的流水线上生产出的不同零件或组件,按照(领导Director)特定要求组装成特定的产品,并给Director提供一个build方法,让其随时可以取走已经组装好的产品。
3、Director(指挥者或者领导):该角色主要根据不同客户的需求,调用不同的Builder对象来组装出特定的产品,提供给客户使用。
[b]为了便于理解,我们假设还有第4个角色:[/b]
4、Client(客户): 客户是产品需求的来源,但是客户不会和生产线或工厂的操作工打交道,他们只会开着车,和领导打交道。
好了,各个角色,我们都定义好了,我们寻找一个场景吧。就拿汽车的生产来说事吧。
[b]我们假设有以下场景:[/b]
Dirctor是生产CarX品牌汽车公司的领导,ClientA和ClientB是分别来自欧洲和亚洲的客户。ClientA希望买到的CarX汽车能够达到更好的节能和经济性需求,ClientB希望买到的车更好的满足安全性和舒适性。Dirctor根据2个客户的需求,命令工程师设计了2套流水线,2条流水线生产的产品都一样,但是产品的性能不同:
A生产线(ProductionLineA)主要生产小排量的发动机和配置不高的ABS安全系统;
B生产线(ProductionLineB)主要生产排量较大的发动机和配置较高的ABS安全系统;
同时为2条生产线安排了不同的组装工程师BuilderA和BuilderB。
产品的组装命令和验收由Dirctor统一负责。
好了,自此,任务分配完毕,我们开始编码工作了。
[b] 首先,对上面问题的分析,我们可以发现,A生产线和B生产线生产的东西名称和功能是一样的,只是性能不同,因此可以对生产线可以进行抽象。[/b]
同样,我们也可以对建造工程师也进行抽象,如下:
好了,方案和任务都安排好了,我们开始具体实施了。
[b] 到此,我们的产品建造实施实体都安排好了,现在需要做的是实现Director(领导者)角色的功能,他负责下发开始启动生产零部件的命令和开始组装的命令。[/b]
领导的任务和职责也安排好了,现在2个客户ClientA和ClientB来和Director签订合同,CarX工厂开始完成客户的任务。代码如下:
运行ClientA输出如下结果:
ClientA 完成与Director生产汽车A的合同
------------生产小排量发动机----------
----------生产普通标准的安全系统-----------
----------生成汽车车身部件-----------
----生产线A完成一辆汽车零部件的生产------
----------完成一辆汽车A的组装调试----------
运行ClientB输出如下结果:
ClientB 完成与Director生产汽车A的合同
------------生产标准排量的发动机----------
----------生产高标准的安全系统-----------
----------生成汽车车身部件-----------
-----生产线B完成一辆汽车零部件的生产----
----------完成一辆汽车B的组装调试----------
到此为止,我们的一个建造者模式的应用实例已经完成了。当然,对生产线和建造者的抽象还可以使用接口来实现,原理都是一样的。
有人总结说Builder模式其实综合了模板方法和工厂模式的思想,其实的确可以这么理解,只是建造者模式对工厂化的生产过程和参与者的角色,做了进一步的细化。大家可以根据不同的需求,选择不同的设计模式。
Builder 模式,即建造者模式,顾名思义,这个模式可能更多的使用在产品的组装中使用,具体说就是在软件产品的组件或模块组装的时候使用。
感觉网络上比较好的解释有:
[b]建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。[/b]
[b]适用的场景:[/b]
1、当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2、当构造过程必须允许被构造的对象有不同的表示时。
首先我们来说下,建造者模式中三个重要的角色:
1、Product (生产者):该角色其实类似于工厂里的流水线,它可以生产各种各样的组件,但是并不知道怎样将这些组件进行组装,进而产生出不同的产品。
2、Builder(建造者):该角色类似流水线上的操作工人,它负责将不同的流水线上生产出的不同零件或组件,按照(领导Director)特定要求组装成特定的产品,并给Director提供一个build方法,让其随时可以取走已经组装好的产品。
3、Director(指挥者或者领导):该角色主要根据不同客户的需求,调用不同的Builder对象来组装出特定的产品,提供给客户使用。
[b]为了便于理解,我们假设还有第4个角色:[/b]
4、Client(客户): 客户是产品需求的来源,但是客户不会和生产线或工厂的操作工打交道,他们只会开着车,和领导打交道。
好了,各个角色,我们都定义好了,我们寻找一个场景吧。就拿汽车的生产来说事吧。
[b]我们假设有以下场景:[/b]
Dirctor是生产CarX品牌汽车公司的领导,ClientA和ClientB是分别来自欧洲和亚洲的客户。ClientA希望买到的CarX汽车能够达到更好的节能和经济性需求,ClientB希望买到的车更好的满足安全性和舒适性。Dirctor根据2个客户的需求,命令工程师设计了2套流水线,2条流水线生产的产品都一样,但是产品的性能不同:
A生产线(ProductionLineA)主要生产小排量的发动机和配置不高的ABS安全系统;
B生产线(ProductionLineB)主要生产排量较大的发动机和配置较高的ABS安全系统;
同时为2条生产线安排了不同的组装工程师BuilderA和BuilderB。
产品的组装命令和验收由Dirctor统一负责。
好了,自此,任务分配完毕,我们开始编码工作了。
[b] 首先,对上面问题的分析,我们可以发现,A生产线和B生产线生产的东西名称和功能是一样的,只是性能不同,因此可以对生产线可以进行抽象。[/b]
package com.icecode.demo;
public abstract class AbstractProductionLine {
//生产汽车发动机
public abstract void createEngine();
//生产汽车安全系统
public abstract void createSecuritySystem();
//生产汽车车身
public abstract void createCarBody();
}
同样,我们也可以对建造工程师也进行抽象,如下:
package com.icecode.demo;
public abstract class AbstractBuilder {
//命令1:启动生产汽车零部件生产线命令
public abstract void buildCarParts();
//命令2:将命令1生产的零部件组装成完整的汽车
public abstract AbstractProductionLine buildCar();
}
好了,方案和任务都安排好了,我们开始具体实施了。
package com.icecode.demo.impl;
import com.icecode.demo.AbstractProductLine;
/**
* 流水线A
* @author zhanche
*
*/
public class ConcreteProductLineA extends AbstractProductLine {
@Override
public void createEngine() {
System.out.println("------------生产小排量发动机----------");
}
@Override
public void createSecuritySystem() {
System.out.println("----------生产普通标准的安全系统-----------");
}
@Override
public void createCarBody() {
System.out.println("----------生成汽车车身部件-----------");
}
}
package com.icecode.demo.impl;
import com.icecode.demo.AbstractProductLine;
/**
* 流水线B
* @author zhanche
*
*/
public class ConcreteProductLineB extends AbstractProductLine {
@Override
public void createEngine() {
System.out.println("------------生产标准排量的发动机----------");
}
@Override
public void createSecuritySystem() {
System.out.println("----------生产高标准的安全系统-----------");
}
@Override
public void createCarBody() {
System.out.println("----------生成汽车车身部件-----------");
}
}
package com.icecode.demo.impl;
import com.icecode.demo.AbstractBuilder;
import com.icecode.demo.AbstractProductLine;
/**
* 建造工人A
* @author zhanche
*
*/
public class ConcreteBuilderA extends AbstractBuilder {
private AbstractProductLine productLineA = new ConcreteProductLineA();
@Override
public void buildCarParts() {
productLineA.createEngine();
productLineA.createSecuritySystem();
productLineA.createCarBody();
System.out.println("-----生产线A完成一辆汽车零部件的生产-----");
}
@Override
public AbstractProductLine buildCar() {
System.out.println("----------完成一辆汽车A的组装调试----------");
return productLineA;
}
}
package com.icecode.demo.impl;
import com.icecode.demo.AbstractBuilder;
import com.icecode.demo.AbstractProductLine;
/**
* 建造工人B
* @author zhanche
*
*/
public class ConcreteBuilderB extends AbstractBuilder {
private AbstractProductLine productLineB = new ConcreteProductLineB();
@Override
public void buildCarParts() {
productLineB.createEngine();
productLineB.createSecuritySystem();
productLineB.createCarBody();
System.out.println("-----生产线B完成一辆汽车零部件的生产----");
}
@Override
public AbstractProductLine buildCar() {
System.out.println("----------完成一辆汽车B的组装调试----------");
return productLineB;
}
}
[b] 到此,我们的产品建造实施实体都安排好了,现在需要做的是实现Director(领导者)角色的功能,他负责下发开始启动生产零部件的命令和开始组装的命令。[/b]
package com.icecode.demo.director;
import com.icecode.demo.AbstractBuilder;
import com.icecode.demo.AbstractProductLine;
import com.icecode.demo.impl.ConcreteBuilderA;
import com.icecode.demo.impl.ConcreteBuilderB;
public class Director {
private AbstractBuilder builderA = new ConcreteBuilderA();
private AbstractBuilder builderB = new ConcreteBuilderB();
public AbstractProductLine getProductA() {
builderA.buildCarParts();
//还可以增加对产品质量抽检等功能
return builderA.buildCar();
}
public AbstractProductLine getProductB(){
builderB.buildCarParts();
//还可以增加对产品质量抽检等功能
return builderB.buildCar();
}
}
领导的任务和职责也安排好了,现在2个客户ClientA和ClientB来和Director签订合同,CarX工厂开始完成客户的任务。代码如下:
package com.icecode.demo.client;
import com.icecode.demo.director.Director;
/**
* 客户A
* @author zhanche
*
*/
public class ClientA {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("ClientA 完成与Director生产汽车A的合同");
Director director = new Director();
director.getProductA();
}
}
package com.icecode.demo.client;
import com.icecode.demo.director.Director;
/**
* 客户B
* @author zhanche
*
*/
public class ClientB {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("ClientB 完成与Director生产汽车A的合同");
Director director = new Director();
director.getProductB();
}
}
运行ClientA输出如下结果:
ClientA 完成与Director生产汽车A的合同
------------生产小排量发动机----------
----------生产普通标准的安全系统-----------
----------生成汽车车身部件-----------
----生产线A完成一辆汽车零部件的生产------
----------完成一辆汽车A的组装调试----------
运行ClientB输出如下结果:
ClientB 完成与Director生产汽车A的合同
------------生产标准排量的发动机----------
----------生产高标准的安全系统-----------
----------生成汽车车身部件-----------
-----生产线B完成一辆汽车零部件的生产----
----------完成一辆汽车B的组装调试----------
到此为止,我们的一个建造者模式的应用实例已经完成了。当然,对生产线和建造者的抽象还可以使用接口来实现,原理都是一样的。
有人总结说Builder模式其实综合了模板方法和工厂模式的思想,其实的确可以这么理解,只是建造者模式对工厂化的生产过程和参与者的角色,做了进一步的细化。大家可以根据不同的需求,选择不同的设计模式。