【活動記錄的意圖】
一個對象,它封裝資料表或視圖中某一行,封裝資料庫訪問,並在這些資料上增加了領域邏輯。
【活動記錄的適用情境】
適用於不太複雜的領域邏輯,如CRUD操作等。
【活動記錄的運行機制】
對象既有資料又有行為。其使用最直接的方法,將資料訪問邏輯置於領域對象中。
活動記錄的本質是一個領域模型,這個領域模型中的類和基資料庫中的記錄結構應該完全符合,類的每個域對應表的每一列。
一般來說,活動記錄包括如下一些方法:
1、由資料行構造一個活動記錄執行個體;
2、為將來對錶的插入構造一個新的執行個體;
3、用靜態尋找方法來封裝常用的SQL查詢和返回活動記錄;
4、更新資料庫並將活動記錄中的資料插入資料庫;
5、擷取或設定域;
6、實現部分商務邏輯。
【活動記錄的優點和缺點】
優點:
1、簡單,容易建立並且容易理解。
2、在使用事務指令碼時,減少代碼複製。
3、可以在改變資料庫結構時不改變領域邏輯。
4、基於單個活動記錄的派生和測實驗證會很有效。
缺點:
1、沒有隱藏關聯式資料庫的存在。
2、僅當活動記錄對象和資料庫中表直接對應時,活動記錄才會有效。
3、要求對象的設計和資料庫的設計緊耦合,這使得項目中的進一步重構很困難
【活動記錄與其它模式】
資料來源架構模式之行資料入口:活動記錄與行資料入口十分類似。二者的主要差別是行資料入口 僅有資料庫訪問而活動記錄既有資料來源邏輯又有領域邏輯。
【活動記錄的PHP樣本】
-
- /**
- * 公司專屬應用程式架構 資料來源架構模式之活動記錄 2010-10-17 sz
- * @author phppan.p#gmail.com http://www.phppan.com
- * 哥學社成員(http://www.blog-brother.com/)
- * @package architecture
- */
-
- /**
- * 定單類
- */
- class Order {
-
- /**
- * 定單ID
- * @var
- */
- private $_order_id;
-
- /**
- * 客戶ID
- * @var
- */
- private $_customer_id;
-
- /**
- * 定單金額
- * @var
- */
- private $_amount;
-
- public function __construct($order_id, $customer_id, $amount) {
- $this->_order_id = $order_id;
- $this->_customer_id = $customer_id;
- $this->_amount = $amount;
- }
-
- /**
- * 執行個體的刪除操作
- */
- public function delete() {
- $sql = "DELETE FROM Order SET WHERE order_id = " . $this->_order_id . " AND customer_id = " . $this->_customer_id;
- return DB::query($sql);
- }
-
- /**
- * 執行個體的更新操作
- */
- public function update() {
- }
-
- /**
- * 插入操作
- */
- public function insert() {
- }
-
- public static function load($rs) {
- return new Order($rs['order_id'] ? $rs['order_id'] : NULL, $rs['customer_id'], $rs['amount'] ? $rs['amount'] : 0);
- }
-
- }
-
- class Customer {
-
- private $_name;
- private $_customer_id;
-
- public function __construct($customer_id, $name) {
- $this->_customer_id = $customer_id;
- $this->_name = $name;
- }
-
- /**
- * 使用者刪除定單操作 此執行個體方法包含了商務邏輯
- * 通過調用定單一實例實現
- * 假設此處是對應的刪除操作(實際中可能是一種以某欄位來標記的假刪除操作)
- */
- public function deleteOrder($order_id) {
- $order = Order::load(array('order_id' => $order_id, 'customer_id' => $this->_customer_id));
- return $order->delete();
- }
-
- /**
- * 執行個體的更新操作
- */
- public function update() {
- }
-
- /**
- * 入口類自身擁有插入操作
- */
- public function insert() {
- }
-
- public static function load($rs) {
- /* 此處可加上緩衝 */
- return new Customer($rs['customer_id'] ? $rs['customer_id'] : NULL, $rs['name']);
- }
-
- /**
- * 根據客戶ID 尋找
- * @param integer $id 客戶ID
- * @return Customer 客戶對象
- */
- public static function find($id) {
- return CustomerFinder::find($id);
- }
-
- }
-
- /**
- * 人員尋找類
- */
- class CustomerFinder {
-
- public static function find($id) {
- $sql = "SELECT * FROM person WHERE customer_id = " . $id;
- $rs = DB::query($sql);
-
- return Customer::load($rs);
- }
- }
-
- class DB {
-
- /**
- * 這隻是一個執行SQL的示範方法
- * @param string $sql 需要執行的SQL
- */
- public static function query($sql) {
- echo "執行SQL: ", $sql, "
";
-
- if (strpos($sql, 'SELECT') !== FALSE) { // 樣本,對於select查詢返回查詢結果
- return array('customer_id' => 1, 'name' => 'Martin');
- }
- }
-
- }
-
- /**
- * 用戶端調用
- */
- class Client {
-
- /**
- * Main program.
- */
- public static function main() {
-
-
- header("Content-type:text/html; charset=utf-8");
-
- /* 載入客戶ID為1的客戶資訊 */
- $customer = Customer::find(1);
-
- /* 假設使用者擁有的定單id為 9527*/
- $customer->deleteOrder(9527);
- }
-
- }
-
- Client::main();
- ?>
同前面的文章一樣,這僅僅是一個活動記錄的樣本,關於活動記錄模式的應用,可以查看Yii架構中的DB類,在其源碼中有一個CActiveRecord抽象類別,從這裡可以看到活動記錄模式的應用
另外,如果從事務指令碼中建立活動記錄,一般是首先將表封裝為入口,接著開始行為遷移,使表深化成為活動記錄。
對於活動記錄中的域的訪問和設定可以如yii架構一樣,使用魔術方法__set方法和__get方法。