設計模式專題(五)——工廠方法模式
設計模式專題(五)——工廠方法模式
(原創內容,轉載請註明來源,謝謝)
一、概述
1、工廠方法與簡單工廠模式區別
工廠方法模式與簡單工廠模式不同
簡單工廠模式最大優點在於工廠類類中包含了必要的邏輯判斷,根據客戶端的選擇條件動態例項化相關的類,對於客戶端來說,除去了與具體產品的依賴。但是,當需要新增、刪除工廠類的功能,違反了開放-封閉原則。
工廠方法模式定義一個用於建立物件的介面,讓子類決定例項化哪一個類,工廠方法使一個類的例項化延遲到其他子類。對工廠需要新增功能,只需要新增具體的工廠類,去繼承工廠介面;再新增實現方法類,去繼承實現介面,符合開放-封閉原則。
2、工廠方法模式存在問題
1)簡單方法模式中在工廠類的邏輯判斷部分,被交到客戶端去實現,因此客戶端處還需要進行邏輯判斷的功能。
2)僅僅為了建立一個特定的ConcreteProduct物件,就不得不建立一個Creator子類。
3、類圖
4、工廠方法模式結構
1)抽象工廠(Creator)角色:是工廠方法模式的核心,與應用程式無關。任何在模式中建立的物件的工廠類必須實現這個介面。
2)具體工廠(ConcreteCreator)角色:這是實現抽象工廠介面的具體工廠類,包含與應用程式密切相關的邏輯,並且受到應用程式呼叫以建立產品物件。
3)抽象產品(Product)角色:工廠方法模式所建立的物件的超型別,也就是產品物件的共同父類或共同擁有的介面。
4)具體產品(ConcreteProduct)角色:這個角色實現了抽象產品角色所定義的介面。某具體產品有專門的具體工廠建立,它們之間往往一一對應。
二、業務實現
1、業務場景
工廠類的設計模式最適合用於需要整合各類相似要求的業務場景,例如對資料庫的操作,就可以使用工廠方法模式,現僅考慮增、刪、改三個操作。
1)工廠介面
工廠介面定義具體工廠類需要的方法,在操作資料庫中如連線不同表,每個表對應一個實體。
2)工廠類
工廠類繼承工廠介面,其定義工廠的具體,實現對具體表產品的操作類的呼叫。
3)產品介面
產品介面定義產品所需要實現的功能的方法,對於每個表,有具體的方法定義。
4)產品類
產品類定義產品的具體功能實體,即對於每個表,有自己獨特的增、刪、改的方法。
這樣的設計很靈活,且新增表格、改動表格在專案中很常見,改動後相應的增刪改的操作肯定有所變動,而工廠方法模式可以很方便的對其進行改動。
另外,每個表有自己的類,因此表格的改動,可以快速找到相關客戶端、服務端的呼叫點,進行進一步的檢查。避免因某個業務調整、表格改動,導致影響其他使用該表格的業務也發生異常。
2、程式實現
<?php
//工廠方法模式,實現資料庫對於每個表的增刪改的定義,建立相關實體
//工廠介面
interface Factory{
publicfunction connectDetailTable($host,$username,$password);
}
//工廠實現類——針對表table1、表table2
class table1Service implements Factory{
publicfunction connectDetailTable($host,$username,$password){
//在已知具體某個表格的情況下,其在哪個資料庫中可以確定
$database= 'database of table1';
returnnew table1Entity(
newPDO('mysql:host='.$server.';dbname='.$database.'',$username,$password)
);
}
}
class table2Service implements Factory{
publicfunction connectDetailTable($host,$username,$password){
$database= 'database of table2';
return new table2Entity(
newPDO('mysql:host='.$server.';dbname='.$database.'',$username,$password)
);
}
}
//產品介面,定義表格應該有的方法,包括新增、批量新增、修改、刪除四種方法
interface Product{
publicfunction __construct($conn);
//createDatas=array(col1=>val1,col2=>val2...)
publicfunction create(array $createDatas);
//createBatchDatas=array(array(col1=>val1,col2=>val2...),array(col1=>val1...)...)
public functioncreateBatch(array $createBatchDatas);
//modifyDatas=array(array(condition1=>val1,condition2=>val2...),array(col1=>val1,col2=>val2...))
publicfunction modify(array $modifyDatas);
//deleteDatas=array(condition1=>val1,condition2=>val2...)
publicfunction delete(array $deleteDatas);
}
//產品實現類,實現產品介面,table1的實體
class table1Entity implements Product{
private$conn;
private$table;
publicfunction __construct($conn){
$this->conn= $conn;
$this->table= 'table1';
}
publicfunction create(array $createDatas){
//...新增邏輯,主要是針對欄位的判斷以及表格具體新增規則的限制,如非空、資料內容等,返回last_insert_id
}
publicfunction createBatch(array $createBatchDatas){
//...批量新增邏輯,主要是針對欄位的判斷以及表格具體新增規則的限制,如非空、資料內容等,返回affect_rows
}
publicfunction modify(array $modifyDatas){
//...修改邏輯,主要是針對表格特有的欄位進行判斷,以及對特定列是否允許修改進行判斷,返回affect_rows
}
publicfunction delete(array $deleteDatas){
//...刪除邏輯,主要是針對表格特定的刪除規則,另外如果有關聯其他表,還需要判斷是需要刪除其他表相關的資料還是不允許刪除此條資料等,返回affect_rows
}
}
//table2的實體不再描述
三、實際意義
資料庫的此設計方案,在實際專案中具有重要意義。
1、規範增刪改的操作,避免使用者隨意對錶進行增刪改。
2、實現對每個表的具體的判斷的“定製化”,針對每個表有自己的要求去設計。
3、便於查詢,降低改動的風險:其實現了工廠方法介面的靈活性,需要新增表格,只需要新增相應的service和entity;修改表格欄位、刪除表格,往往需要檢查程式的呼叫點,則只需要檢查相應service、entity的呼叫點即可。
——written by linhxx 2017.07.30
相關閱讀: