建造者模式
一,什么是建造者模式
定义:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是23种设计模式中创建型模式中的一种,我们知道创建模式有五种,分别是单例模式、工厂方法模式、抽象工厂模式、原型模式及建造者模式,这些模式无一例外都是用于创建某个类的对象实例。
什么场景可以用建造者模式:当一个类的构造过多时并且个别参数可选填,这时可以考虑使用用建造者模式。
目的:是为了分离对象的属性与创建过程。
二,代码实现
实现建造者模式有两种方式:传统方式实现、静态内部类方式
废话不多说了直接上代码吧,代码更直观,下面一步一步来定义一个建造者模式。
下面例子以创建一个人为例,默认普通人,人有身体、耳朵、眼睛、牙齿等待。
1,Build 传统方式实现:
下面案例中我把构建得过程交给客户端不在单独实现,
第一步,首先创建我们的目标对象,
package pattern.build;
/**
* 产品
* @author ningbeibei
*/
public class Product {
private String body="普通身体";
private String ear = "普通耳朵";
private String eye = "普通眼睛";
private String mouth = "普通牙齿";
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getEar() {
return ear;
}
public void setEar(String ear) {
this.ear = ear;
}
public String getEye() {
return eye;
}
public void setEye(String eye) {
this.eye = eye;
}
public String getMouth() {
return mouth;
}
public void setMouth(String mouth) {
this.mouth = mouth;
}
}
第二步,定义建造者抽象类
package pattern.build;
/**
* 建造者抽象类
* @author ningbeibei
*/
public abstract class AbstractBuilder {
abstract AbstractBuilder body(String msg);//身体
abstract AbstractBuilder mouth(String msg);//嘴巴
abstract AbstractBuilder ear(String msg);//耳朵
abstract AbstractBuilder eye(String msg);//眼睛
abstract Product getProduct();//获取产品
}
AbstractBuilder 抽象类并实现抽象方法 ,注意:具体建造者类中构造函数用来创建目标对象,
package pattern.build;
/**
* 具体建造者
* @author ningbeibei
*/
public class Build extends AbstractBuilder{
//声明产品属性
private Product product;
//具体建造者构造函数用来创建产品对象
public Build() {
product = new Product();
}
@Override
AbstractBuilder body(String msg) {
product.setBody(msg);
return this;
}
@Override
AbstractBuilder mouth(String msg) {
product.setMouth(msg);
return this;
}
@Override
AbstractBuilder ear(String msg) {
product.setEar(msg);
return this;
}
@Override
AbstractBuilder eye(String msg) {
product.setEye(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
我这没有写指挥者类,这个指挥者我交给客户端来做,建造者模式一般在构造复杂对象时可以考虑使用,根据不同得场景使用不同得设计模,但是在真正使用时基本上不会单独使用一种设计模,大多数都是混合使用,这就需要阅读代码者需要对设计模式足够了解和掌握。
package pattern.build;
/**
* 建造者模式测试类
* @author ningbeibei
*/
public class Test {
public static void main(String[] args) {
//创建构建对象
Build build1 = new Build();
//这里可以用方法链来组建对象
Product p = build1.body("金身").ear("顺风耳").getProduct();
System.out.println(p.getBody()+" "+p.getEar()+" "+p.getEye()+" "+p.getMouth());
}
}
2,静态内部类方式实现:
a.首先创建一个 StaticBuild 类并定义属性封装get方法,我代码中定义属性用 final 修饰的,所以不需要set方法,把初始化属性放到静态内部类中;
b.在 StaticBuild 类中创建静态内部类 Builder (静态内部类)类;
c.创建 StaticBuild 类构造方法并用 private 修饰,参数为 Builder (静态内部类)类型;
d.在 Builder 中定义属性,可以把 StaticBuild 类属性复制到 Builder 类中(静态内部类属性去除 final 修饰符);
e.在 Builder 中创建设置函数,对 StaticBuild 中那些参数进行赋值,返回值为 Builder 类型的实例;
g.在 Builder 中创建一个 build() 方法,在其中构建 StaticBuild 的实例并返回;
请看完成代码:
package pattern.build;
/**
* 静态内部类实现建造者模式
* @author ningbeibei
*/
public class StaticBuild {
private final String name;
private final String age;
private final String shengao;
private final String toufa;
//构造函数
private StaticBuild(Builder build){
this.name = build.name;
this.age = build.age;
this.shengao = build.shengao;
this.toufa = build.toufa;
}
//静态内部类
public static class Builder{
private String name;
private String age;
private String shengao;
private String toufa;
//构造函数
public Builder(String name,String age) {
this.name = name;
this.age = age;
}
//设置属性值,返回Builder对象
public Builder setShengao(String shengao) {
this.shengao = shengao;
return this;
}
//设置属性值,返回Builder对象
public Builder setToufa(String toufa) {
this.toufa = toufa;
return this;
}
//构建StaticBuild对象并返回
public StaticBuild build(){
return new StaticBuild(this);
}
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
public String getShengao() {
return shengao;
}
public String getToufa() {
return toufa;
}
}
测试类
package pattern.build;
/**
* 建造者模式测试类
* @author ningbeibei
*/
public class Test {
public static void main(String[] args) {
//静态内部类式建造者模式
StaticBuild build = new StaticBuild.Builder("张三", "30").setShengao("178").setToufa("红").build();
System.out.println("姓名:"+build.getName());
System.out.println("年龄:"+build.getAge());
System.out.println("身高:"+build.getShengao());
System.out.println("头发:"+build.getToufa());
}
}
三,写的不足之处请批评指正