问题的提出:

有些类很容易创建对象,直接调用其构造方法,例如Student student = new Student(“1001”,”zhang”,21); 之所以容易创建,因为其类成员都是基本数据类型或者封装类,或者字符串。但是如果对象的类成员还是对象,那么创建这个对象还需要产生该对象成员的具体对象。

public class Unit1 {
}
public class QuestionProduct {
    Unit1 u1;
    Unit2 u2;
    Unit3 u3;
    public void createUnit1(){
        u1 = new Unit1();
    }
    public void createUnit2(){
        u2 = new Unit2();
    }
    public void createUnit3(){
        u3 = new Unit3();
    }
    public void composite(){

    }
    public static void main(String[] args) {
        QuestionProduct p = new QuestionProduct();
        p.createUnit1();
        p.createUnit2();
        p.createUnit3();
        p.composite();
    }
}

 

Unit123为各java对象,main方法可以知道,只有当运行完p.composite()方法后,Product才真正的创建起来,问题来了,如果有两类Product对象,又或许有很多类成员。又或者随着Product产品种类的增加和减少,必须修改已有的源代码。于是为了解决这类问题,生成器模式应运而生!

生成器模式的主要思路是:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。简单来说,不在同一类里面创建该类的类成员,而是把类成员的创建交给另一个类,该类就叫做生成器!

public interface IBuild {
    public Product create();
}
public class BuildProduct implements IBuild {
    Product p = new Product();

    public void createUnit1(){
        //创建u1
    }
    public void createUnit2(){
        //创建u2
    }
    public void createUnit3(){
        //创建u3
    }
    public Product composite(){
        //关联Unit1,Unit2,Unit3
        return p;
    }
    public Product create(){
        createUnit1();
        createUnit2();
        createUnit3();
        return composite();
    }
}

通过上面的代码可以知道,如果需求分析发生变化,只需要增加或者删除相应的生成器类BuildProduct即可,并不需要修改已有的类代码。

在这基础上,再定义一个调度类,是对生成器接口的IBuild的封装。

public class Director {
    private IBuild iBuild;
    public Director(IBuild iBuild){
        this.iBuild = iBuild;
    }
    public Product build(){
        //System.out.println("test");
        iBuild.createUnit1();
        iBuild.createUnit2();
        iBuild.createUnit3();
        return iBuild.composite();
    }

    public static void main(String[] args) {
        IBuild iBuild = new BuildProduct();
        Director director = new Director(iBuild);
        Product p = director.build();
    }
}

这样就构成生成器模式的一般模式了!一般分为以下三个步骤

1)定义产品类

2)定义n个生成器Build类

3)定义一个统一调度类Director类

Java设计模式:生成器模式

对于Director的理解:与常规的接口相比,生成器接口IBuild是特殊的,它是一个流程控制接口。该接口中定义的方法必须依照某种顺序执行,一个都不能少。因此在程序中一个要体现出“流程”这一特点。而Director类的作用就是对“流程”的封装类,其中的build方法决定了具体的流程控制过程。

对于上面的生成器模式,假如要生成两种Product产品,一种需要三种过程,一种需要四种过程,那么用上面的生成器模式(Model1)就不行了,因为它要求创建产品的过程必须相同(Interface IBuild定义好了创建的过程)。于是引起下面Model2的设计。

Java设计模式:生成器模式

Model2IBuild接口仅仅定义多态create()方法

public interface IBuild {
    public Product create();
}

 而在具体生成器类重写多态create()方法,并调用多个个非多态方法,最终返回Product对象。

public class BuildProduct implements IBuild {
    Product p = new Product();

    public void createUnit1(){
        //创建u1
    }
    public void createUnit2(){
        //创建u2
    }
    public void createUnit3(){
        //创建u3
    }
    public Product composite(){
        //关联Unit1,Unit2,Unit3
        return p;
    }
    public Product create(){
        createUnit1();
        createUnit2();
        createUnit3();
        return composite();
    }
}

Director类

public class Director {
    private IBuild iBuild;
    public Director(IBuild iBuild){
        this.iBuild = iBuild;
    }
    public Product build(){
        return iBuild.create();
    }
}

对代码进行仔细分析可以发现,具体生成器多态的create()方法中包含了创建Product对象的全过程,Director类中的方法就显得重复了。在这种设计中其实是可以省略Director类的,这就说明了在生成器模式中,抽象生成器和具体生成器是必须的。

而指挥类需要在实际问题中认真考虑,加以取舍!进一步思考,可以把IBuild定义成泛型接口,不仅仅是Product产品,也可以是其他需要生成器魔术的产品都可以从这接口派生。

 

除了以上两种实现方式,还有第三种生成器功能的设计模式

Model3:利用Product派生方法,可以实现类似生成器功能

Java设计模式:生成器模式

具体代码如下

1.Product类

public abstract class Product {
    Unit1 u1;
    Unit2 u2;
    Unit3 u3;
    abstract void createUnit1();        //表明子类要创建Unit1,2,3,并组合它
    abstract void createUnit2();
    abstract void createUnit3();
    abstract void composite();
}

View Code