现实中有这样一种情况:有些对象的内部结构比较复杂,一般是由各种对象数据组合而来的.而且在某些
情况下,对象的属性必须按照一定的顺序赋值才有意义。这样无论是使用工厂模式、工厂方法模式亦或是抽
象工厂模式都不符合该情景。
解决上述问题,应该使用建造者模式。
建造者(Builder)模式:
建造者模式也叫生成器模式,他可以将一个产品对象的内部表象与产品的产生过程分离开来,从而
使一个建造过程生成具有不同内部表象的产品对象。简单的说建造产品的过程,就是“组合零件”的过
程,这些零件就相当于产品对象的内部表象,但是因为组合零件的过程十分复杂。因此,这个过程
往往被“外部化”到一个Builder对象去,Builder返回给用户一个全部零件构建完毕的产品对象。
说了这么多,接下来看看Builder模式的结构吧,了解其工作原理。
建造者(Builder)模式结构图:
建造者(Builder)模式角色:
建造者角色(Builder):是一个接口,用以规范产品对象的各个组成成分的建造,独立于应用程
序的商业逻辑。具体建造者必须实现接口。
具体建造者(Concrete Builder): 需要实现建造者角色接口,用于创建产品实例,并提供创建
的产品实例。
指导者角色(Director):调用ConcreteBuilder类创建对象,其本身并没有产品对象类的具体内容。
产品角色(Product):是该模式中要创建的复杂对象。
Director是用于和客户端打交道的角色,他将客户端创建产品的请求划分为对各个零件的创建请求,
再将这些请求交给Concrete Builder,Concrete Builder的创建过程对于客户端来说是隐藏的。
下面在以一个简单的例子程序说明、学习建造者模式!(关于台式机组装的问题)
一个台式机就相当于一个复杂对象,他拥有CPU,MONITOR,KEYBOARD等等组件,其创建过程
可以用创建者模式模拟。
首先构建一些Computer对象所需要的组件:
package com.kiritor;
/**CPU*/
public class CPU {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CPU() {
// TODO Auto-generated constructor stub
}
public CPU(String name)
{
this.name=name;
}
}
/**Keyboard*/
package com.kiritor;
public class Keyboard {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Keyboard() {
// TODO Auto-generated constructor stub
}
public Keyboard(String name)
{
this.name=name;
}
}
/**Monitor*/
package com.kiritor;
public class Monitor {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Monitor() {
// TODO Auto-generated constructor stub
}
public Monitor(String name)
{
this.name=name;
}
}
Computer类:
package com.kiritor;
/**
* @author Kiritor 产品类
*/
public class Computer {
private CPU cpu;
private Keyboard keyboard;
private Monitor monitor;
public CPU getCpu() {
return cpu;
}
public void setCpu(CPU cpu) {
this.cpu = cpu;
}
public Keyboard getKeyboard() {
return keyboard;
}
public void setKeyboard(Keyboard keyboard) {
this.keyboard = keyboard;
}
public Monitor getMonitor() {
return monitor;
}
public void setMonitor(Monitor monitor) {
this.monitor = monitor;
}
}
抽象建造者类:
package com.kiritor;
/**
* @author Kiritor
* 抽象生成器*/
public abstract class Builder {
abstract public void buildCPU();
abstract public void buildMonitor();
abstract public void buildKeyboard();
public Computer getComputer()
{
return null;
}
}
具体建造者类:
package com.kiritor;
/**
* @author Kiritor
* 具体生成类*/
public class ConcreteBuilder extends Builder{
private Computer computer =new Computer();
@Override
public void buildCPU() {
// TODO Auto-generated method stub
computer.setCpu(new CPU("i5"));
}
@Override
public void buildKeyboard() {
// TODO Auto-generated method stub
computer.setKeyboard(new Keyboard("巧克力键盘"));
}
public void buildMonitor() {
computer.setMonitor(new Monitor("三星"));
}
public Computer ConcreteBuilder() {
// TODO Auto-generated constructor stub
return computer;
}
}
指导类:
package com.kiritor;
/**
* @author Kiritor
* 向导类*/
public class Director {
/*指导复杂对象的创建过程,参数为建造类*/
public void buildComputer(Builder builder)
{
/*这里可以决定个对象的建造次序*/
builder.buildCPU();
builder.buildKeyboard();
builder.buildMonitor();
}
}
测试类:
package com.kiritor;
public class Client {
public static void main(String[] args) {
//首先实例化一个指导类
Director director = new Director();
//其次实例化一个具体建造类
Builder builder = new ConcreteBuilder();
director.buildComputer(builder);//客户端对复杂产品创建过程是不可见的
Computer computer = builder.getComputer();
}
}
由以上代码可以看出,建造者模式中,客户端只是负责创建指导者和建造者对象,由
指导者
控制建造者创建产品,最后建造者把产品返回给客户端。因此产品的创建细节对于客户端来说
是隐藏的。
既然知道了建造者模式的工作方式,那么他的具体使用场景是什么呢?
1、需要生成的产品对象有复杂的结构
2、生成的产品的属性可以相互依赖,建造者模式可以强迫他们的顺序
建造者模式是产品的内部表象可以独立变化,建造者模式可以对客户端隐藏产品的组成细节