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

固然這只是簡單的測試代碼,在實際應用中還要注意不少問題。

相關文章
相關標籤/搜索