Builder Pattern
出自VFP Wiki
(修訂版本間差異)
小 (→Builder Pattern) |
小 (→Builder Pattern) |
||
第13行: | 第13行: | ||
參考資料: | 參考資料: | ||
- | http://www.dotspace.idv.tw/Patterns/Jdon_Builder.htm | + | *http://www.dotspace.idv.tw/Patterns/Jdon_Builder.htm |
- | http://140.109.17.201/Jyemii/patternscolumn/articles/DesignPatternPart(2).htm | + | *http://140.109.17.201/Jyemii/patternscolumn/articles/DesignPatternPart(2).htm |
- | Design Pattern 中譯本 - 葉秉哲譯 | + | *Design Pattern 中譯本 - 葉秉哲譯 |
範例程式: | 範例程式: |
在2005年4月23日 (六) 09:53的最新修訂版本
Builder Pattern
給予適當的建構資料,就可以得到我們所需要的物件.
詳細的說明可以參考後面所附的參考資料,那些資料就已經寫的很好了,我想我沒必要再畫蛇添足 ^_^.
最初製作這個 SQL Builder class 的時候是想說,我只要給予它一些欄位和條件,他就會自動幫我產生 SQL 敘述,而不必再去考量 SQL 敘述是否正確啊...等等的問題.剛好想到 Builder pattern 其實很適合,所以就實做看看.
目前這個 class 已經蠻齊全了,不過有些地方可以再加強.
- Join 部分
- 資料型態轉換,作的不好~應該可以再更精簡,更可靠.
- 傳入 select - sql 敘述,就能產生 delete-sql, update-sql.
- ...
參考資料:
- http://www.dotspace.idv.tw/Patterns/Jdon_Builder.htm
- http://140.109.17.201/Jyemii/patternscolumn/articles/DesignPatternPart(2).htm
- Design Pattern 中譯本 - 葉秉哲譯
範例程式:
* 主程式 LOCAL lc_sql LOCAL lo_builder lo_builder=CREATEOBJECT("csqlbuilder") lo_builder.ADDCOLUMN("u_id") lo_builder.ADDCOLUMN("u_name") lo_builder.setTable("users") lo_builder.addWhere("", "u_id", "=", "drury") lo_builder.addOrderby( "u_id" ) lo_builder.addGroupby( "u_id" ) ? "=====" ? "select sql::" ?? lo_builder.getSelectSQL() lo_builder.reconf() lo_builder.addPair("u_id", "ellery") lo_builder.addPair("u_name", "ellery") lo_builder.setTable("users") lo_builder.addWhere("", "u_id", "=", "drury") ? "=====" ? "insert sql::" + lo_builder.getInsertSQL() ? "update sql::" + lo_builder.getUpdateSQL() ? "delete sql::" + lo_builder.getDeleteSQL() * * Builder pattern 類別實作 * 此類別適用環境: VFP 8.0 * 類別定義開始 * DEFINE CLASS CSQLBuilder AS CUSTOM ADD OBJECT PROTECTED m_pairs AS COLLECTION ADD OBJECT PROTECTED m_where AS COLLECTION ADD OBJECT PROTECTED m_groupby AS COLLECTION ADD OBJECT PROTECTED m_orderby AS COLLECTION ADD OBJECT PROTECTED m_keys as collection m_table = "" && the table m_targettype="" && cursor, table m_target="" && name * Init PROCEDURE INIT ENDPROC * Destroy PROCEDURE DESTROY ENDPROC * Reconfigure PROCEDURE reconf * MSDN said: pass -1 will clear all items THIS.m_pairs.REMOVE( -1 ) THIS.m_where.REMOVE( -1 ) THIS.m_groupby.REMOVE( -1 ) THIS.m_orderby.REMOVE( -1 ) THIS.m_table = "" THIS.m_targettype="" THIS.m_target="" ENDPROC * addColumns PROCEDURE ADDCOLUMN( c_field AS STRING ) THIS.m_pairs.ADD( .NULL., c_field ) ENDPROC PROCEDURE addWhere( c_logical AS STRING, c_field AS STRING, c_operator AS STRING, o_value AS OBJECT ) THIS.m_where.ADD( o_value, c_logical + c_field + c_operator ) ENDPROC PROCEDURE addPair( c_field AS STRING, o_value AS OBJECT ) THIS.m_pairs.ADD( o_value, c_field ) ENDPROC PROCEDURE addGroupby( c_field AS STRING ) THIS.m_groupby.ADD( .NULL., c_field ) ENDPROC PROCEDURE addOrderby( c_field AS STRING ) THIS.m_orderby.ADD( .NULL., c_field ) ENDPROC PROCEDURE addKey( c_field as String ) this.m_keys.add( .null., c_field ) ENDPROC PROCEDURE addJoin * todo: this is the most hard part. ENDPROC PROCEDURE setTable( c_table AS STRING ) THIS.m_table=c_table ENDPROC PROCEDURE setTarget( c_type AS STRING, c_target AS STRING ) THIS.m_targettype=c_type THIS.m_target=c_string ENDPROC PROCEDURE getInsertSQL LOCAL i LOCAL lc_sql LOCAL lc_fields, lc_values, lc_type lc_fields="" lc_values="" lc_sql="insert into " + THIS.m_table + " " FOR i=1 TO THIS.m_pairs.COUNT lc_fields=lc_fields+THIS.m_pairs.GETKEY(i) IF( i+1 <= THIS.m_pairs.COUNT ) lc_fields=lc_fields+"," ENDIF lc_type=VARTYPE( THIS.m_pairs.ITEM(i) ) DO CASE CASE lc_type="C" lc_values=lc_values+ "'" + THIS.m_pairs.ITEM(i)+ "'" CASE INLIST( lc_type, "N", "Y" ) lc_values=lc_values + ALLTRIM( STR(THIS.m_pairs.ITEM(i) ) ) CASE lc_type="D" lc_values=lc_values + "{^" + DTOC( THIS.m_pairs.ITEM(i) ) + "}" CASE lc_type="L" lc_values=lc_values + IIF( THIS.m_pairs.ITEM(i), ".T.", ".F." ) CASE lc_type="X" lc_values=lc_values + ".null." ENDCASE IF( i+1 <= THIS.m_pairs.COUNT ) lc_values=lc_values+"," ENDIF NEXT lc_sql=lc_sql + "(" + lc_fields + ") values (" + lc_values + ")" RETURN lc_sql ENDPROC PROTECTED PROCEDURE getWhereSQL LOCAL lc_sql IF( THIS.m_where.COUNT >=1 ) lc_sql=" where " ELSE lc_sql="" ENDIF FOR i=1 TO THIS.m_where.COUNT lc_type=VARTYPE( THIS.m_where.ITEM(i) ) DO CASE CASE lc_type="C" lc_value= "'" + THIS.m_where.ITEM(i)+ "'" CASE INLIST( lc_type, "N", "Y" ) lc_value= ALLTRIM( STR(THIS.m_where.ITEM(i) ) ) CASE lc_type="D" lc_value="{" + DTOC( THIS.m_where.ITEM(i) ) + "}" CASE lc_type="L" lc_value=IIF( THIS.m_where.ITEM(i), ".T.", ".F." ) CASE lc_type="X" lc_value=".null." ENDCASE lc_sql=lc_sql + THIS.m_where.GETKEY(i) + lc_value IF( i+1 <= THIS.m_where.COUNT ) lc_sql=lc_sql+"," ENDIF NEXT RETURN lc_sql ENDPROC PROCEDURE getOnlyKey( o_collection AS COLLECTION ) LOCAL i LOCAL lc_sql lc_sql="" FOR i=1 TO o_collection.COUNT lc_sql=lc_sql+o_collection.GETKEY(i) IF( i+1 <= o_collection.COUNT ) lc_sql=lc_sql+"," ENDIF NEXT RETURN lc_sql ENDPROC PROCEDURE getOrderBySQL LOCAL lc_sql lc_sql=THIS.getOnlyKey( THIS.m_orderby ) IF( EMPTY(lc_sql) ) RETURN lc_sql ELSE RETURN " order by " + lc_sql ENDIF ENDPROC PROCEDURE getGroupbySQL LOCAL lc_sql lc_sql=THIS.getOnlyKey( THIS.m_groupby ) IF( EMPTY(lc_sql) ) RETURN lc_sql ELSE RETURN " group by " + lc_sql ENDIF ENDPROC PROCEDURE getSelectSQL LOCAL i LOCAL lc_sql, lc_where, lc_orderby, lc_groupby lc_sql="select " FOR i=1 TO THIS.m_pairs.COUNT lc_sql=lc_sql+THIS.m_pairs.GETKEY(i) IF( i+1 <= THIS.m_pairs.COUNT ) lc_sql=lc_sql+"," ENDIF NEXT lc_sql=lc_sql + " from " + THIS.m_table lc_where=THIS.getWhereSQL() lc_sql=lc_sql + lc_where lc_orderby=THIS.getOrderBySQL() lc_sql=lc_sql+lc_orderby lc_groupby=THIS.getGroupbySQL() lc_sql=lc_sql+lc_groupby RETURN lc_sql ENDPROC PROCEDURE getDeleteSQL LOCAL lc_sql LOCAL i LOCAL lc_value, lc_type, lc_where lc_sql="delete from " + THIS.m_table lc_where=THIS.getWhereSQL() lc_sql=lc_sql+lc_where RETURN lc_sql ENDPROC PROCEDURE getUpdateSQL LOCAL i LOCAL lc_sql LOCAL lc_fields, lc_values, lc_type, lc_where lc_fields="" lc_values="" lc_sql="update " + THIS.m_table + " set " FOR i=1 TO THIS.m_pairs.COUNT lc_sql=lc_sql+THIS.m_pairs.GETKEY(i)+"=" lc_type=VARTYPE( THIS.m_pairs.ITEM(i) ) DO CASE CASE lc_type="C" lc_sql=lc_sql + "'" + THIS.m_pairs.ITEM(i) + "'" CASE INLIST( lc_type, "N", "Y" ) lc_sql=lc_sql + ALLTRIM( STR(THIS.m_pairs.ITEM(i) ) ) CASE lc_type="D" lc_sql=lc_sql + "{^" + DTOC( THIS.m_pairs.ITEM(i) ) + "}" CASE lc_type="L" lc_values=lc_sql + IIF( THIS.m_pairs.ITEM(i), ".T.", ".F." ) CASE lc_type="X" lc_values=lc_sql + ".null." ENDCASE IF( i+1 <= THIS.m_pairs.COUNT ) lc_sql=lc_sql+"," ENDIF NEXT * handle where clause. lc_where=THIS.getWhereSQL() lc_sql=lc_sql+lc_where RETURN lc_sql ENDPROC PROCEDURE getKeyFieldList() LOCAL i LOCAL lc_fields IF( THIS.m_keys.COUNT >=1 ) lc_fields="" ELSE RETURN "" ENDIF FOR i=1 TO THIS.m_keys.COUNT lc_fields=lc_fields+this.m_keys.getKey(i) IF( i+1 <= THIS.m_keys.COUNT ) lc_fields=lc_fields+"," ENDIF NEXT RETURN lc_fields ENDPROC PROCEDURE getTable() RETURN THIS.m_table ENDPROC PROCEDURE getUpdatableFieldList() LOCAL i, lc_fields lc_fields="" FOR i=1 TO THIS.m_pairs.COUNT lc_fields=lc_fields+THIS.m_pairs.GETKEY(i) IF( i+1 <= THIS.m_pairs.COUNT ) lc_fields=lc_fields+"," ENDIF NEXT RETURN lc_fields ENDPROC PROCEDURE getUpdateNameList() LOCAL i, lc_fields lc_fields="" FOR i=1 TO THIS.m_pairs.COUNT lc_fields=lc_fields+THIS.m_pairs.GETKEY(i)+" " lc_fields=lc_fields+this.m_table+"."+this.m_pairs.getkey(i) IF( i+1 <= THIS.m_pairs.COUNT ) lc_fields=lc_fields+"," ENDIF NEXT RETURN lc_fields ENDPROC ENDDEFINE * 類別定義結束