Java设计模式:生成器模式

问题的提出:java

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

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产品种类的增长和减小,必须修改已有的源代码。因而为了解决这类问题,生成器模式应运而生!sql

生成器模式的主要思路是:将一个复杂的构建与其表示相分离,使得一样的构建过程能够建立不一样的表示。简单来讲,不在同一类里面建立该类的类成员,而是把类成员的建立交给另外一个类,该类就叫作生成器!数据库

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();
    }
}

复制代码

这样就构成生成器模式的通常模式了!通常分为如下三个步骤ide

1)定义产品类测试

2)定义n个生成器Build类ui

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

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

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

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派生方法,能够实现相似生成器功能

具体代码以下

1.Product类

 View Code

2.生成器BuildProduct类

 View Code

3.指挥者类Director

 View Code

总而言之,对于生成器模式建立复制对象而言,主要的原则仍是对象构建过程与表示相分离。这是一个总的思想,实现具体形式不是一成不变,大能够设计本身专属的生成器模式框架。重要的是思想,而不是实现形式!

 

最后再说说生成器模式的应用场景,其中一个比较重要的做用就是解决同流程,异界面的手段之一。

例如在登陆下经常都会分不一样的角色,好比教务系统登陆区分教师和学生。通常的应用也分为管理员以及普通用户。不一样的角色登陆后或显示不一样的页面。下面就教学管理系统这个例子简单说明。

        

学生的具体信息在student表中,教师的具体信息在teacher表中。一个经常使用的功能是:管理员为学生和教师在login表中分配了用户名和帐号,同时在studentteacher表中创建关键字user的记录。可是其余具体信息如姓名年龄等是空的。

所以须要学生或者教师在登陆后首先完善我的信息。下面正是利用生成器模式设计“我的信息完善”的基础代码。

 Mysql 表的简单设计

 View Code

1)界面抽象生成器UIBuilder

复制代码

package BuildModel.Example;import javax.swing.*;/**
 * Created by lenovo on 2017/4/18. */public abstract class UIBuilder {    protected JPanel panel = new JPanel();    abstract public void addUI();                   //造成界面
    abstract public void registerMsg();             //注册消息
    abstract public void initialData(String user);  //初始化界面数据
    public JPanel getPanel(){                       //返回界面面板对象
        return panel;
    }
}

复制代码

2)具体学生界面生成器类StudentBuilder

 View Code

3)DbProc数据库自定义封装类(注意测试时候strPwd要加上本身本地mysql的帐户密码)

 

 View Code

 

4)具体教师界面生成器TeacherBuilder(相似,这里就不写了)

5)流程指挥类Director

复制代码

package BuildModel.Example;import javax.swing.*;/**
 * Created by lenovo on 2017/4/18. */public class Director {    private UIBuilder builder;    public Director(UIBuilder builder){        this.builder = builder;
    }    public JPanel build(String user){
        builder.addUI();                //初始化界面
        builder.registerMsg();          //登记消息
        builder.initialData(user);      //填充帐号为user的初始界面显示数据
        return builder.getPanel();
    }
}

复制代码

6)测试类

 View Code

固然这只是简单的测试代码,在实际应用中还要注意不少问题。

相关文章
相关标签/搜索