在类的应用中,有些简单的类是容易创建对象的,直接调用构造方法即可。例如:
Student student = new Student("1001", "张三", 20);
Circle circle = new Circle(10.0f);
而有些类却不宜直接创建对象的,成员变量是自定义类型,例如:
public class Product {
Unit1 u1;
Unit2 u2;
Unit3 u3;
}
上述代码可知,Product由Unit1、Unit2、Unit3三个单位组成,不能简单地由Product product = Product(Unit1 u1, Unit2 u2, Unit3)获得,必须先生成具体的u1、u2、u3,然后才能获得Product对象。简单实现如下:
public class Product {
Unit1 u1;
Unit2 u2;
Unit3 u3;
public void createUnit1(){
// u1=...
}
public void createUnit2(){
// u2=...
}
public void createUnit3(){
// u3=...
}
public void composite(){
// u1+u2+u3
}
public static void main(String[] args) {
Product p = new Product();
p.createUnit1();
p.createUnit2();
p.createUnit3();
p.composite();
}
}
上述代码仅解决了一类Product对象的创建问题,如果有两类Product呢?
public class Product {
Unit1 u1;
Unit2 u2;
Unit3 u3;
// 创建第一种Product对象方法组
public void createUnit1() {
// u1=...
}
public void createUnit2() {
// u2=...
}
public void createUnit3() {
// u3=...
}
// 创建第二种Product对象方法组
public void createUnit1_2() {
// u1=...
}
public void createUnit2_2() {
// u2=...
}
public void createUnit3_2() {
// u3=...
}
public void composite(){
// u1+u2+u3
}
public static void main(String[] args) {
int type = 1; // 创建第一种Product对象标识
Product p = new Product();
if (type == 1) {
p.createUnit1();
p.createUnit2();
p.createUnit3();
p.composite();
} else if (type == 2){
p.createUnit1_2();
p.createUnit2_2();
p.createUnit3_2();
p.composite();
}
p.composite();
}
}
随着Product产品种类的增多和减少,必须修改已有的源代码。
生成器模式也称为建造者模式。生成器模式的意图在于将一个复杂的队形的构建与其表示相分离,使得同样的建造过程可以创建不同的表示。
在软件设计中,有时候面临一个非常复杂的对象的创建工作。这个复杂的对象通常可以分成几个较小的子部分,由各个子对象组合出这个复杂的对象的过程相对来说比较稳定,但是子对象的创建过程各不相同并且可能发生变化。
根据OOD中的OCP原则,应该将子对象的构建过程进行变化封装。代码如下
产品
public class Product {
Unit1 u1;
Unit2 u2;
Unit3 u3;
}
生成器类接口Build
public interface Build {
void createUnit1();
void createUnit2();
void createUnit3();
Product composite();
}
第一种生成器
public class BuildProduct1 implements Build {
Product p = new Product();
@Override
public void createUnit1() {
// p.u1 = ...
}
@Override
public void createUnit2() {
// p.u2 = ...
}
@Override
public void createUnit3() {
// p.u3 = ...
}
@Override
public Product composite() {
// ...
return p;
}
}
第二种生成器(若需求发生变化,只需添加或删除相应的生成器类)
public class BuildProduct2 implements Build {
Product p = new Product();
@Override
public void createUnit1() {
// p.u1 = ...
}
@Override
public void createUnit2() {
// p.u2 = ...
}
@Override
public void createUnit3() {
// p.u3 = ...
}
@Override
public Product composite() {
// ...
return p;
}
}
统一的调度类
public class Director {
private Build build;
public Director(Build build){
this.build = build;
}
public Product build(){
build.createUnit1();
build.createUnit2();
build.createUnit3();
return build.composite();
}
public static void main(String[] args) {
Build build = new BuildProduct1();
Director director = new Director(build);
Product p = director.build();
}
}
通过上述代码,可知生成器设计模式涉及四个关键角色:
与常规接口相比,生成器接口Build是特殊的流程控制接口,该接口中定义的方法必须依据某种顺序执行,一个都不能少。因此,在程序设计中需要体现 流程 这一特点。Director类是对 流程 的封装类,其中build()方法决定了流程的控制过程。
若Build接口中,不包含定义子过程的方法,仅包含创建方法create()。即不清楚生产的产品分为多少个子过程。
Build接口
public interface Build {
Product create();
}
具体的生成器类
public class BuildProduct1 implements Build {
private Product p = new Product();
private void createUnit1(){
// p.u1 = ...
}
private void createUnit2(){
// p.u2 = ...
}
private void createUnit3(){
// p.u3 = ...
}
public Product composite() {
// ...
return p;
}
@Override
public Product create() {
createUnit1();
createUnit2();
createUnit3();
return composite();
}
}
指挥者类
public class Director {
private Build build;
public Director(Build build){
this.build = build;
}
public Product build(){
return build.create();
}
}
对于生成器模式来说,抽象生成器和具体生成器是必不可缺的。上述代码中,Director类若不需要也可以删除。
Build接口可定义成泛型接口,不单单表示生成Product对象
public interface Build<T> {
T create();
}
public abstract class Product {
Unit1 u1;
Unit2 u2;
Unit3 u3;
abstract void createUnit1();
abstract void createUnit2();
abstract void createUnit3();
abstract void composite();
}
public class BuildProduct1 extends Product{
@Override
void createUnit1() {
// u1 = ...
}
@Override
void createUnit2() {
// u2 = ...
}
@Override
void createUnit3() {
// u3 = ...
}
@Override
void composite() {
// 关联u1,u2,u3
}
}
public class Director {
Product p;
public Director(Product p){
this.p = p;
}
public void build(){
p.createUnit1();
p.createUnit2();
p.createUnit3();
p.composite();
}
}
数据库数据导入功能类,将不同格式的学生成绩文件导入到数据库表score中,表结构如下。
序号 | 字段名 | 说明 | 关键字 |
---|---|---|---|
1 | StudNO | 学号 | √ |
2 | Studname | 姓名 | |
3 | Score | 成绩 |
虽然学生成绩文件的格式不同,但导入score表中的流程是相同的,如下图
关键代码如下
public abstract class AbstractBuild {
public abstract boolean open(String strPath);
public abstract boolean hasNext();
public abstract Score next();
public abstract void close();
public boolean saveToDb(Score s){
String strSQL = "INSERT INTO score VALUES('"+s.getStudno()+"','"+s.getName()+"',"+s.getScore()+")";
DbProc dbobj = new DbProc();
try {
dbobj.connect();
dbobj.executeUpdate(strSQL);
dbobj.close();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
public class Score {
private String studno;
private String name;
private int score;
public String getStudno() {
return studno;
}
public void setStudno(String studno) {
this.studno = studno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
public class Director {
AbstractBuild build;
public Director(AbstractBuild build){
this.build = build;
}
public void build(String strPath){
build.open(strPath);
while (build.hasNext()){
Score s = build.next();
build.saveToDb(s);
}
build.close();
}
}