对设计模式不是很熟悉,现在碰到一个比较棘手的问题,不知道应该如何设计,请大家帮忙看一看。现在有两种用于快速处理订单的业务A、业务B,分别用于处理订单A和订单B,他们的逻辑都是相似的,基本逻辑就是:(1)初始化业务的各项基础数据
(2)接受一个订单,放入到待处理订单缓冲
(3)从待处理缓冲读取一个订单并开始处理,并将处理完的订单放入到已处理缓冲
(4)定期检测已处理缓存,当已处理缓冲区达到一定数量之后就同步写入数据库上述逻辑的设计是考虑到订单的数量非常庞大(高峰时段每秒需要接受10~100个订单),并且订单发出后用户无需等待处理状态,所有订单在第二步都是可以成功处理的。每个订单如果即时写入数据库,会造成数据库无法负担。因此业务A和业务B都包含下列线程:
(1)主线程:用于接受客户端请求
(2)初始线程:完成系统初始化
(3)处理线程:处理队列
(4)同步更新线程:更新到数据库系统采用.Net Remoting技术进行部署,为了减少并发冲突,我的想法是:主线程使用实例变量形式,而待处理缓冲和已处理缓冲都采用静态变量形式,响应的初始线程、处理线程和同步更新线程都均采用静态变量形式。因此我打算写一个基础类,业务A和业务B都该基础类进行继承,基类的代码可以简单概况为:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Threading;
using System.Text;namespace MyProgram
{
public class OrderBaseObj : MarshalByRefObject
{
// 待处理订单列表
protected static List<OrderItem> lstUnHandle = new List<OrderItem>(); // 已处理订单列表
protected static List<OrderItem> lstHandle = new List<OrderItem>(); // 初始化是否完成标记
protected static bool blnInitFinished = false; // 待执行的数据库事务表
protected static List<string> lstUpdateCommand = new List<string>(); // 初始化线程
protected static Thread threadInit = null; // 处理线程
protected static Thread threadHandle = null; // 数据库同步线程
protected static Thread threadDB = null; static OrderBaseObj()
{
ThreadStart tst = new ThreadStart(ThreadInit_Start);
threadInit = new Thread(tst);
threadInit.Priority = ThreadPriority.BelowNormal;
threadInit.Start(); tst = new ThreadStart(ThreadHandle_Start);
threadHandle = new Thread(tst);
threadHandle.Priority = ThreadPriority.Lowest;
threadHandle.Start(); tst = new ThreadStart(ThreadDB_Start);
threadDB = new Thread(tst);
threadDB.Priority = ThreadPriority.Lowest;
threadDB.Start();
} /// <summary>
/// 添加一个PV到待处理区
/// </summary>
public void AddPV(OrderItem order)
{
lstUnHandle.Add(order);
} // 初始线程启动方法
private static void ThreadInit_Start()
{
Init();
blnInitFinished = true;
} // 初始化抽象方法
protected static abstract bool Init(); // 处理线程启动方法
private static void ThreadHandle_Start()
{
while (true)
{
OrderItem order=lstUnHandle[0];
lstUnHandle.RemoveAt(0); HandleOrder(order);
lstHandle.Add(order);
if(lstHandle.Count>100)
{
string strCommmand=HandleUpdateCommmand();
lstUpdateTrans.Add(strCommand);
lstHandle.Clear();
}
}
} // 订单处理的抽象方法,每个子类必须实现该方法
protected abstract static void HandleOrder(OrderItem order); // 返回处理数据库同步更新命令
protected abstract static string HandleUpdateCommmand(); // 同步线程启动方法
private static void ThreadDB_Start()
{
while (true)
{
if (lstUpdateTrans.Count > 0)
{
string strCommand=lstUpdateTrans[0];
lstUpdateTrans.RemoveAt(0); DBObj db=new DBObj();
db.Execute(strCommand);
db.CloseConn();
} Thread.Sleep(new TimeSpan(0, 0, 2));
}
}
}
}上面代码的问题就是:静态方法不能描述为抽象方法,如果不采用基类的方式,直接在业务A或者业务B里面实现,上面的思路是没有问题的(不采用抽象方法),当然很多代码会重复,如果需要增加订单类型,就要增加业务类,维护起来不方便。如果一定要实现一个基类,那么这么基类应该怎么写呢?
(2)接受一个订单,放入到待处理订单缓冲
(3)从待处理缓冲读取一个订单并开始处理,并将处理完的订单放入到已处理缓冲
(4)定期检测已处理缓存,当已处理缓冲区达到一定数量之后就同步写入数据库上述逻辑的设计是考虑到订单的数量非常庞大(高峰时段每秒需要接受10~100个订单),并且订单发出后用户无需等待处理状态,所有订单在第二步都是可以成功处理的。每个订单如果即时写入数据库,会造成数据库无法负担。因此业务A和业务B都包含下列线程:
(1)主线程:用于接受客户端请求
(2)初始线程:完成系统初始化
(3)处理线程:处理队列
(4)同步更新线程:更新到数据库系统采用.Net Remoting技术进行部署,为了减少并发冲突,我的想法是:主线程使用实例变量形式,而待处理缓冲和已处理缓冲都采用静态变量形式,响应的初始线程、处理线程和同步更新线程都均采用静态变量形式。因此我打算写一个基础类,业务A和业务B都该基础类进行继承,基类的代码可以简单概况为:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Threading;
using System.Text;namespace MyProgram
{
public class OrderBaseObj : MarshalByRefObject
{
// 待处理订单列表
protected static List<OrderItem> lstUnHandle = new List<OrderItem>(); // 已处理订单列表
protected static List<OrderItem> lstHandle = new List<OrderItem>(); // 初始化是否完成标记
protected static bool blnInitFinished = false; // 待执行的数据库事务表
protected static List<string> lstUpdateCommand = new List<string>(); // 初始化线程
protected static Thread threadInit = null; // 处理线程
protected static Thread threadHandle = null; // 数据库同步线程
protected static Thread threadDB = null; static OrderBaseObj()
{
ThreadStart tst = new ThreadStart(ThreadInit_Start);
threadInit = new Thread(tst);
threadInit.Priority = ThreadPriority.BelowNormal;
threadInit.Start(); tst = new ThreadStart(ThreadHandle_Start);
threadHandle = new Thread(tst);
threadHandle.Priority = ThreadPriority.Lowest;
threadHandle.Start(); tst = new ThreadStart(ThreadDB_Start);
threadDB = new Thread(tst);
threadDB.Priority = ThreadPriority.Lowest;
threadDB.Start();
} /// <summary>
/// 添加一个PV到待处理区
/// </summary>
public void AddPV(OrderItem order)
{
lstUnHandle.Add(order);
} // 初始线程启动方法
private static void ThreadInit_Start()
{
Init();
blnInitFinished = true;
} // 初始化抽象方法
protected static abstract bool Init(); // 处理线程启动方法
private static void ThreadHandle_Start()
{
while (true)
{
OrderItem order=lstUnHandle[0];
lstUnHandle.RemoveAt(0); HandleOrder(order);
lstHandle.Add(order);
if(lstHandle.Count>100)
{
string strCommmand=HandleUpdateCommmand();
lstUpdateTrans.Add(strCommand);
lstHandle.Clear();
}
}
} // 订单处理的抽象方法,每个子类必须实现该方法
protected abstract static void HandleOrder(OrderItem order); // 返回处理数据库同步更新命令
protected abstract static string HandleUpdateCommmand(); // 同步线程启动方法
private static void ThreadDB_Start()
{
while (true)
{
if (lstUpdateTrans.Count > 0)
{
string strCommand=lstUpdateTrans[0];
lstUpdateTrans.RemoveAt(0); DBObj db=new DBObj();
db.Execute(strCommand);
db.CloseConn();
} Thread.Sleep(new TimeSpan(0, 0, 2));
}
}
}
}上面代码的问题就是:静态方法不能描述为抽象方法,如果不采用基类的方式,直接在业务A或者业务B里面实现,上面的思路是没有问题的(不采用抽象方法),当然很多代码会重复,如果需要增加订单类型,就要增加业务类,维护起来不方便。如果一定要实现一个基类,那么这么基类应该怎么写呢?
| | |
基类 基类 基类这就要3个基类了
然后设计模式上你去仔细看看模板方法那一个模式吧,正好可以解决你的这个问题。
LOOK这个对你的开发应该有帮助..
还有OO提倡瘦对象,即单一职能..看了LZ的思路是有OO的思想的,我的意见就是把这个胖对象拆成几个瘦对象..
// 初始化抽象方法
protected static abstract bool Init();
需要修改一下:
protected abstract bool Init();
不要用静态
你想给业务A和业务B写一个基类,这不重要,我想.当然你可以这么做.
由于涉及订单处理这样的业务逻辑,可以考虑采用workflow,不过似乎目前不微软的workfolw不支持2003,那你只能用开源的了.主程序将订单(订单要求可序列化)传给workflow(宿主在windows service),由workflow处理,处理后的订单直接插入微软的消息队列(参看.net petshop 4.0),这样你不必担心订单的丢失,你的方法似乎有丢失订单的可能性.再由消息队列的Windows service将处理后的订单同步(或异步)插入数据库.
至于你说的线程A线程B我想都是针对业务逻辑的,没必要和数据操作放在一起来处理,采用分层的结构比较好.以上仅供参考.