C# MVC模式中應(yīng)該怎樣區(qū)分應(yīng)用程序邏輯(Controller層)和業(yè)務(wù)邏輯(Model層)?
現(xiàn)在的大部分框架都是 MVC 模式,但 MVC 三個(gè)部分怎么配合,這里做了一點(diǎn)總結(jié):
基本原則:業(yè)務(wù)邏輯代碼應(yīng)該寫在 M 里面,而應(yīng)用程序邏輯應(yīng)該寫在 C 里面。V 只是單純的展示數(shù)據(jù)。
舉個(gè)簡(jiǎn)單例子吧:用戶往購(gòu)物車添加一個(gè)商品
用戶點(diǎn)擊商品的“添加到購(gòu)物車”按鈕,引起一次請(qǐng)求。服務(wù)器開始處理該請(qǐng)求,過(guò)程:
1、檢查當(dāng)前用戶是否有權(quán)限(比如是否已經(jīng)登錄、用戶帳戶狀態(tài)、是否可以購(gòu)物等)
2、檢查要添加的商品ID是否有效、
3、檢查要添加的商品庫(kù)存是否足夠
4、將商品加入購(gòu)物車,并保存購(gòu)物車狀態(tài)
5、反饋信息
在上述流程中:
1: 是應(yīng)用程序邏輯(一般由框架實(shí)現(xiàn)):因?yàn)楹汀疤砑由唐返劫?gòu)物車”這個(gè)業(yè)務(wù)沒(méi)有直接關(guān)系
2: 業(yè)務(wù)邏輯:不能購(gòu)買不存在的商品,這是業(yè)務(wù)進(jìn)行的基本條件
3: 業(yè)務(wù)邏輯:商品庫(kù)存決定了是否可以購(gòu)買此商品,這是業(yè)務(wù)進(jìn)行的基本條件
4: 業(yè)務(wù)邏輯
5: 應(yīng)用程序邏輯
用代碼表示的,可能像下面這樣:
// Cart控制器
class Controller_Cart
{
function actionAddGoods()
{
$goods_id = (int)$_GET['goods_id'];
Cart::instance()->add($goods_id)->save();
echo '添加成功';
}
}
// Cart 模型
class Cart
{
/**
* 購(gòu)物車中的所有項(xiàng)目
*/
public $items = array();
/**
* 單子模式,返回購(gòu)物車對(duì)象的唯一實(shí)例
*/
static function instance()
{
...
}
function add($goods_id, $quantity = 1)
{
$goods = Goods::find($goods_id)->get();
// 檢查 id 和庫(kù)存數(shù)
if ($goods->id && $quantity > $goods->remaining)
{
// 添加商品到購(gòu)物車
$this->items[] = array($goods, $quantity);
}
else
{
throw new CartExecption('無(wú)效的商品 ID');
}
return $this;
}
}
這個(gè)代碼不完整,但是演示了最重要的部分,就是應(yīng)用程序邏輯和業(yè)務(wù)邏輯的分離。
如果這個(gè)流程走下去,用戶要結(jié)算了,那么代碼如下:
class Controller_Cart
{
function actionCheckOut()
{
Cart::instance()->checkout();
echo '成功';
}
}
class Cart
{
function checkout()
{
// 開啟一個(gè)數(shù)據(jù)庫(kù)事務(wù)
....
try
{
// 創(chuàng)建一個(gè)新的訂單對(duì)象
// $this->owner 是當(dāng)前購(gòu)物車的所有者(用戶)
$order = new Order($this->owner);
// 將購(gòu)物車中的所有商品添加到訂單中
foreach ($this->items as $item)
{
list($goods, $quantity) = $item;
$order->add($goods, $quantity);
}
// 保存訂單
$order->save();
// 清空購(gòu)物車
$this->items = array();
}
catch (Exception $ex)
{
// 出錯(cuò)了,回滾事務(wù)
....
// 再重新拋出異常
throw $ex;
}
// 返回新建的訂單
return $order;
}
}
class Order extends Model
{
public $items;
function add($goods, $quantity)
{
$this->items[] = array($goods, $quantity);
return $this;
}
function save()
{
foreach ($this->items as $item)
{
list($goods, $quantity) = $item;
// 保存訂單時(shí),減少訂單中每一個(gè)商品的庫(kù)存數(shù)
$goods->decrRemaining($quantity);
}
// 調(diào)用父類的保存
parent::save();
return $this;
}
}
結(jié)算的代碼很容易理解:
1、調(diào)用購(gòu)物車的 checkout() 方法
2、開啟數(shù)據(jù)庫(kù)事務(wù),這樣當(dāng)保存訂單失敗時(shí)(例如庫(kù)存數(shù)不夠)則回滾,確保數(shù)據(jù)庫(kù)內(nèi)容沒(méi)有受影響
3、將購(gòu)物車中的所有商品添加到訂單
4、調(diào)用訂單對(duì)象的 save() 方法
4.1、遍歷訂單的所有項(xiàng)目,減少商品的庫(kù)存(如果此時(shí)失敗,商品的 decrRemaining() 方法會(huì)拋出異常)
4.2、調(diào)用模型父類的 save() 方法
5、清空購(gòu)物車,返回新建的訂單對(duì)象
整個(gè)流程我們假定創(chuàng)建訂單就等同于客戶確認(rèn)訂單,此時(shí)減少庫(kù)存。也有可能是后臺(tái)確認(rèn)訂單配貨后才減少庫(kù)存,這和賣家的經(jīng)營(yíng)策略有關(guān)。
這兩個(gè)例子里面,業(yè)務(wù)邏輯都在模型中實(shí)現(xiàn),控制器(也就是封裝應(yīng)用程序邏輯的層)僅僅完成處理輸入數(shù)據(jù)、調(diào)用業(yè)務(wù)方法、反饋結(jié)果等任務(wù)。
- C#實(shí)現(xiàn)DataTable映射成Model的方法(附源碼)
- C# DataTable常見(jiàn)用法匯總
- C#讀取Excel到DataTable的方法示例
- C#實(shí)現(xiàn)Json轉(zhuǎn)DataTable并導(dǎo)出Excel的方法示例
- C#中DataTable 轉(zhuǎn)實(shí)體實(shí)例詳解
- 詳解C#把DataTable中數(shù)據(jù)一次插入數(shù)據(jù)庫(kù)的方法
- C#實(shí)現(xiàn)利用泛型將DataSet轉(zhuǎn)為Model的方法
- C# DataTable與Model互轉(zhuǎn)的示例代碼
相關(guān)文章
解析如何正確使用SqlConnection的實(shí)現(xiàn)方法
本篇文章對(duì)如何正確使用SqlConnection的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C#實(shí)現(xiàn)文件上傳及文件下載功能實(shí)例代碼
文件上傳文件下載需求在項(xiàng)目中經(jīng)常會(huì)遇到,今天小編給大家分享C#實(shí)現(xiàn)文件上傳及文件下載功能實(shí)例代碼,需要的朋友參考下吧2017-08-08c#使用Dataset讀取XML文件動(dòng)態(tài)生成菜單的方法
這篇文章主要介紹了c#使用Dataset讀取XML文件動(dòng)態(tài)生成菜單的方法,涉及C#使用Dataset操作XML文件的相關(guān)技巧,需要的朋友可以參考下2015-05-05C#中的除法運(yùn)算符與VB.NET中的除法運(yùn)算符
這篇文章主要介紹了C#中的除法運(yùn)算符與VB.NET中的除法運(yùn)算符,需要的朋友可以參考下2014-10-10