说明:开发语言:在本文中,使用的是C#
一、目录
二、单例模式
/// <summary>
/// TDataAccessFactory静态属性
/// </summary>
private static TDataAccessFactory _Instance = null;
/// <summary>
/// TDataAccessFactory静态属性
/// </summary>
public static TDataAccessFactory Instance
{
get
{
if (_Instance == null)
{
_Instance = new TDataAccessFactory();
}
return _Instance;
}
}
#endregion
三、简单工厂模式
/// 取Connection对象
/// </summary>
/// <param name="Info"></param>
/// <param name="Connection"></param>
/// <returns></returns>
public Boolean Connection(TConnectionInfo Info, ref TCustomConnection Connection)
{
try
{
switch (Info.AdapterKind)
{
case TAdapterKind.akMSSQL:
Connection.MSSQL.TConnection _MSSQLConnection = new Connection.MSSQL.TConnection();
_MSSQLConnection.DBID = Info.DBID;
_MSSQLConnection.AdapterKind = Info.AdapterKind;
_MSSQLConnection.ConnectionString = Info.ConnectionString;
Connection = (QPCenterExpress.Data.Connection.TCustomConnection)_MSSQLConnection;
return true;
case TAdapterKind.akORACLE:
Connection.Oracle.TConnection _NOTEConnection = new Connection.Oracle.TConnection();
_NOTEConnection.DBID = Info.DBID;
_NOTEConnection.AdapterKind = Info.AdapterKind;
_NOTEConnection.ConnectionString = Info.ConnectionString;
Connection = (QPCenterExpress.Data.Connection.TCustomConnection)_NOTEConnection;
return true;
case TAdapterKind.akNOTE:
Connection.NOTE.TConnection _QPCenterNoteConnection = new Connection.NOTE.TConnection();
_QPCenterNoteConnection.DBID = Info.DBID;
_QPCenterNoteConnection.AdapterKind = Info.AdapterKind;
_QPCenterNoteConnection.ConnectionString = Info.ConnectionString;
Connection = (QPCenterExpress.Data.Connection.TCustomConnection)_QPCenterNoteConnection;
return true;
case TAdapterKind.akMYSQL:
Connection.MySQL.TConnection _MySQLConnection = new Connection.MySQL.TConnection();
_MySQLConnection.DBID = Info.DBID;
_MySQLConnection.AdapterKind = Info.AdapterKind;
_MySQLConnection.ConnectionString = Info.ConnectionString;
Connection = (QPCenterExpress.Data.Connection.TCustomConnection)_MySQLConnection;
return true;
default:
MessageInfo.Exception.Value = "未知的适配器类型";
return false;
}
}
catch (Exception Ex)
{
MessageInfo.Exception.GUID = "{D1022C7E-D827-4F2C-BBF1-17A69CDE75B5}";
if (Info == null)
MessageInfo.Exception.Value = "请选择数据源";
else
MessageInfo.Exception.Value = Ex.Message;
return false;
}
}
四、代理模式
定义:在客户端和目标对象之间增加一层中间层,让代理对象代替目标对象,然后客户端只需要访问代理对象,由代理对象去帮我们去请求目标对象并返回结果给客户端
实例核心:客户端调用负载均衡分配置器(代理),来获得服务地址跟端口。然后根据端口号访问对应的服务
应用实例代码
public Stream GetServiceAndPort(Stream requestStream)
{
string context = "";
StreamReader Reader = new StreamReader(requestStream);
//Text日志中的报文信息
String Text = Reader.ReadToEnd();
Reader.Dispose();
context = HttpUtility.UrlDecode(Text.Replace("+", "%2B"));
DataTable dtSrv = new DataTable();
DataSet ds = new DataSet();
try
{
if (_TBServiceList == null)
_TBServiceList = HostProvider.GetServiceList();
var results = from item in HostProvider.WCFServiceList
//where item.DllName.Contains("QPCenterApplicationService.dll")
where item.DllName.Contains("QPCenterContainerService.dll")
orderby item.LinkCount ascending
select item;
if (results.Count<WCFServiceItem>() > 0)
{
var val = results.First<WCFServiceItem>();
val.LinkCount += 1;
dtSrv = _TBServiceList.Clone();
DataRow dr = _TBServiceList.Select("FMID='" + val.ServiceID + "'")[0];
//dr["FHOST"] = GetAddressIP();
if (oneOrMoreServer == 0)
{
dr["FHOST"] = context.Split(':')[1].Remove(0, 2);
}
dtSrv.ImportRow(dr);
dtSrv.TableName = "ServiceAndPort";
// QPCenter_WindowAPI.PostMessage(val., QPCenter_WindowAPI.FStartMessage, IntPtr.Zero, IntPtr.Zero);
}
ds.Tables.Add(dtSrv);
string retJson = TBase_Json.ToJson(ds);
//string strResponse = "{\"flag\":0,\"msg\":" + "\"\"" + ",\"data\":" + retJson + "}";
MemoryStream _Stream = new MemoryStream();
Byte[] bText = Encoding.UTF8.GetBytes(retJson);
_Stream.Write(bText, 0, bText.Length);
_Stream.Position = 0;
return _Stream;
}
catch (Exception ex)
{
//InteractiveXml.Result = false;
//特殊状况会发生未知错误进到这里
return null;
}
}
五、观察者模式
定义:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的行为
实例核心:报表结果观察器,查看缓存报表结果状态,完成状态(isRunSysReport)即显示报表结果。
注:本例里,是只有一个观察者,应用上,可以把isRunSysReport,做成1,2,3,4...数值,观察员者1看1,观察者2专2,等
应用实例代码
private void timer1_Tick(object sender, EventArgs e)
{
if (AppGlobal.cltUser.dtUserReportRNC.Rows.Count > 0)
{
if (isRunSysReport) return;
DataRow dt = AppGlobal.cltUser.dtUserReportRNC.Rows[0];
DataTable ds = mod_ComFunc.LoadFilterCache("dxSysReport", "TaskID", dt["TaskID"].ToString());
if (ds.Rows.Count < 1) return;
DataRow dsMenu = ds.Rows[0];
if (dsMenu["State"].ToString() == "1")
{
isRunSysReport = true;
if (DevMsgBox.ShowQuestion(dt["TaskName"].ToString() + "已经查询好,是否打开,也可稍后去报表队例任务列表中查看?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
DataTable ds2 = mod_ComFunc.LoadFilterCache("dxMENUE", "FMID", dt["DisplayMode"].ToString());
DataRow dsMenu2 = ds2.Rows[0];
string sCaption = String.Format("{0}[{1}]", dsMenu2["FUNCNAME"].ToString(), dsMenu2["FuncNo"].ToString());
TabItem item = FindOpenMenu(dsMenu2["FuncName"].ToString());
if (item != null)
{
tabStripWork.SelectedTab = item;
isRunSysReport = false;
AppGlobal.cltUser.dtUserReportRNC.Rows.Remove(dt);
if ((tabStripWork.SelectedTab.ItemData == null) || (tabStripWork.SelectedTab.Name == "tabItemFirst")) return;
BSBaseForm currentfrm = tabStripWork.SelectedTab.ItemData as BSBaseForm;
currentfrm.OpenForm(dsMenu["TaskID"].ToString());
return;
}
TBaseMenu menuItem = new TBaseMenu();
menuItem.FuncID = dt["DisplayMode"].ToString();
menuItem.DLLName = dsMenu2["DLLName"].ToString();
menuItem.ClassName = dsMenu2["ClassName"].ToString();
menuItem.DisplayName = sCaption;
menuItem.FuncType = 1;
menuItem.FModuleID = dsMenu2["FModuleID"].ToString();
menuItem.InitParams = dsMenu2["InitParams"].ToString();
menuItem.MainForm = _newMainFrom;
AppGlobal.cltUser.dtUserReportRNC.Rows.Remove(dt);
isRunSysReport = false;
menuItem.Execute(dsMenu["TaskID"].ToString());
}
}
}
}
六、外观模式
定义:外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用
实例核心:统一的接口入口,调用不同的逻辑与提供不能的参数。
应用实例代码
/// <summary>
/// 统一服务访问接口 mProxyID、controller、method 为地址参数
/// </summary>
/// <param name="mProxyID">授权ID</param>
/// <param name="controller">功能模块</param>
/// <param name="method">功能方法名称</param>
/// <param name="jsondata">提交的数据</param>
/// <returns></returns>
public Stream ProcessRequest(Stream requestStream)
{
string strResponse = "";
string mProxyID = "";
string controller = "";
string method = "";
string context = "";
object[] retObjs;
DateTime dt1 = DateTime.Now;
try
{
NameValueCollection nvc = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters;
mProxyID = nvc["mProxyID"].ToString();
controller = nvc["controller"].ToString();
method = nvc["method"].ToString();
StreamReader Reader = new StreamReader(requestStream);
//Text日志中的报文信息
String Text = Reader.ReadToEnd();
Reader.Dispose();
context = HttpUtility.UrlDecode(Text.Replace("+", "%2B"));
LogMsgHelper.WriteLogsToQueue(LogLevel.INFO, SysType.Core, LogType.SysLog, "客户端请求:" + context, "应用服务日志:" + TServiceParams.Instance.ServiceName + "端口" + TServiceParams.Instance.Port, "", dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterContainerService.ProcessRequest");
string retJson = "";
if (controller.ToLower() == "testwcfcontroller")
{
retJson = TBase_Json.ToJson("Test success");
}
else
{
if (mProxyID == "0")
{
mProxyID = TRemoteLoader.CreateObject();
TRemoteLoader.AddClient(mProxyID, "", DateTime.Now);
}
//retJson = TRemoteLoader.ProcessRequest(mProxyID, controller, method, context);
retObjs = TBase_Json.ToArray(context);
if (controller == "Login")
{
List<object> objList = retObjs.ToList();
objList.Add(mProxyID);
retObjs = objList.ToArray();
}
retJson = QPCenterExpress.Common.RouterAcc.Base_LogicController.ExecuteLogic(controller, method, retObjs);
}
strResponse = "{\"flag\":0,\"msg\":" + "\"\"" + ",\"data\":" + retJson + "}";
LogMsgHelper.WriteLogsToQueue(LogLevel.INFO, SysType.Core, LogType.SysLog, Text, "执行成功", "", dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterContainerService.ProcessRequest");
}
catch (Exception err)
{
if (err.InnerException == null)
{
//LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.SysLog, "客户端请求:" + context, "功能服务日志:" + TServiceParams.Instance.ServiceName + "端口" + TServiceParams.Instance.Port, err.Message, dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterContainerService.ProcessRequest");
strResponse = "{\"flag\":1,\"msg\":" + "\"" + err.Message + "\"" + "}";
}
else
{
//LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.SysLog, "客户端请求:" + context, "功能服务日志:" + TServiceParams.Instance.ServiceName + "端口" + TServiceParams.Instance.Port, err.Message, dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterContainerService.ProcessRequest");
strResponse = "{\"flag\":1,\"msg\":" + "\"" + err.InnerException.Message + "\"" + "}";
}
LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.SysLog, "客户端请求:" + context, "功能服务日志:" + TServiceParams.Instance.ServiceName + "端口" + TServiceParams.Instance.Port, err.Message, dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterContainerService.ProcessRequest");
}
MemoryStream _Stream = new MemoryStream();
Byte[] bText = Encoding.UTF8.GetBytes(strResponse);
_Stream.Write(bText, 0, bText.Length);
_Stream.Position = 0;
return _Stream;
}
七、享元模式
定义:运用共享技术有效地支持大量细粒度的对象
实例核心:整个系统的逻辑跟数据访问对象,分别装到了逻辑跟数据访问公共静态数据字典里了,供整系统统一高速调用。
应用实例代码
public class AutoSelectLogic
{
public static Dictionary<string, MethodInfo> dicLogicMethodInfo = new Dictionary<string, MethodInfo>();
public static Dictionary<string, object> dicLogicClass = new Dictionary<string, object>();
/// <summary>
/// 逻辑层程序集
/// </summary>
public static List<string> LogicDll;
public static bool LoadLogic()
{
var LogicDlls = System.Configuration.ConfigurationManager.AppSettings["LogicDll"];
if (LogicDlls == null)
{
return false;
}
string[] dllfiles = LogicDlls.Split(new char[] { '|' });
LogicDll = dllfiles.ToList();
for (int k = 0; k < LogicDll.Count; k++)
{
//加载程序集(dll文件地址),使用Assembly类
Assembly assembly = System.Reflection.Assembly.LoadFrom(QPCenterExpress.Common.AppGlobal.AppRootPath + "\\Logic\\" + LogicDll[k]);
if (assembly != null)
{
Type[] types = assembly.GetTypes();
for (int i = 0; i < types.Length; i++)
{
if (types[i].FullName.Contains(LogicDll[k].Replace(".dll", ".")))
{
//创建该对象的实例,object类型,参数(名称空间+类)
object instance = assembly.CreateInstance(LogicDll[k].Replace(".dll", ".") + types[i].Name);
if (!dicLogicClass.ContainsKey(types[i].Name))
{
//如果不存在key
dicLogicClass.Add(types[i].Name, instance);
}
MethodInfo[] property = types[i].GetMethods();
for (int h = 0; h < property.Length; h++)
{
MethodInfo methodInfo = property[h];
if (!dicLogicMethodInfo.ContainsKey(types[i].Name + "." + methodInfo.Name))
{
dicLogicMethodInfo.Add(types[i].Name + "." + methodInfo.Name, methodInfo);
}
}
}
}
}
}
return true;
}
}
八、命令模式
定义:把一个操作或者行为抽象为一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开。命令模式的实现可以提供命令的撤销和恢复功能。
实例核心:任务包(带命令以及参数),调度服务负责发送命令,执行服务负责解析命令及参数,并调用不同逻辑执行命令。
应用实例代码
如下是调度里的,入队,即发布命令
/// <summary>调度线程(入队)</summary>
static void DataWhDispatchInQueue()
{
while (true)
{
//Thread.Sleep(25000);
object[] retObjs = new object[] { "FEXECSTATES=0 and FSTATES=1 ", "" };
DateTime dt1 = DateTime.Now;
try
{
string retJson = QPCenterExpress.Common.RouterAcc.Base_LogicController.ExecuteLogic("DataWh", "GetDataWhStatusData", retObjs);
DataSet tempFileServiceDs = TBase_Json.JsonToDataSet(retJson);
tempFileServiceDs.Tables[0].TableName = "BS_SYS_DataWarehouseExec";
for (int i = 0; i < tempFileServiceDs.Tables[0].Rows.Count; i++)
{
if (Convert.ToDateTime(tempFileServiceDs.Tables[0].Rows[i]["FEXECTIME"]) <= DateTime.Now)
{
TaskPackageInfo taskPackage = Newtonsoft.Json.JsonConvert.DeserializeObject<TaskPackageInfo>(tempFileServiceDs.Tables[0].Rows[i]["TASKPACKAGE"].ToString());
EnqueueDataWh(taskPackage);
tempFileServiceDs.Tables[0].Rows[i]["FEXECSTATES"] = "1";
tempFileServiceDs.Tables[0].AcceptChanges();
tempFileServiceDs.Tables[0].Rows[i].SetModified();
Object[] objUpdatd = new Object[] { "dxBS_SYS_DataWarehouseExec", "FMID", TBase_Json.ToJson(tempFileServiceDs) };
QPCenterExpress.Common.RouterAcc.Base_LogicController.ExecuteLogic("DataWh", "UpdatdDataWhStatusData", objUpdatd);
}
}
//等待0.5秒 更改为 等待 30s
Thread.Sleep(30000);
//break;
}
catch (Exception err)
{
LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.SysLog, retObjs, "数据仓库调度入队", err.ToString(), dt1, DateTime.Now, "QPCenterServices.ServiceEngine.TQPCenterDispatchService.SyncCache");
}
}
}
如下是调度里的,出队,即执行命令
/// <summary>调度线程(出队)</summary>
static void DataWhDispatchOutQueue()
{
while (true)
{
object[] retObjs = new object[] { "", "" };
DateTime dt1 = DateTime.Now;
try
{
if (_services.Count > 0 & _dataWhs.Count > 0)
{
ExecuteServiceInfo serverInfo = OutServiceStatus();
TaskPackageInfo dataWhtaskPack = null;
lock (_cacheLocker)
{
if (_dataWhs.Count > 0)
{
dataWhtaskPack = _dataWhs.Dequeue(); // 有任务时,出列任务
if (dataWhtaskPack == null) // 退出机制:当遇见一个null任务时,代表任务结束
return;
}
}
if (dataWhtaskPack != null)
{
object[] retDataWh = new object[] { "MXBH = '" + dataWhtaskPack.DispatchItemNo + "'", "" };
string retJson = QPCenterExpress.Common.RouterAcc.Base_LogicController.ExecuteLogic("DataWh", "GetDataWhStatusData", retDataWh);
DataSet tempFileServiceDs = TBase_Json.JsonToDataSet(retJson);
if (tempFileServiceDs.Tables[0].Rows[0]["FEXECSTATES"].ToString() == "1")
{
//更新数据仓库状态
tempFileServiceDs.Tables[0].TableName = "BS_SYS_DataWarehouseExec";
tempFileServiceDs.Tables[0].Rows[0]["FEXECSTATES"] = "2";
tempFileServiceDs.Tables[0].Rows[0]["FIP"] = serverInfo.ServerIp;
tempFileServiceDs.Tables[0].Rows[0]["FPORT"] = serverInfo.ServerPort;
tempFileServiceDs.Tables[0].AcceptChanges();
tempFileServiceDs.Tables[0].Rows[0].SetModified();
Object[] objUpdatd = new Object[] { "dxBS_SYS_DataWarehouseExec", "FMID", TBase_Json.ToJson(tempFileServiceDs) };
QPCenterExpress.Common.RouterAcc.Base_LogicController.ExecuteLogic("DataWh", "UpdatdDataWhStatusData", objUpdatd);
//写通知到执行服务
Object[] obj = new Object[] { dataWhtaskPack.SourceDb, dataWhtaskPack.SourceScript, dataWhtaskPack.TargetDb, dataWhtaskPack.TargetTable, dataWhtaskPack.TargetScript, dataWhtaskPack.TaskNo, dataWhtaskPack.DispatchItemNo, dataWhtaskPack.AllOrAdd, dataWhtaskPack.ReadPackProperty, dataWhtaskPack.WritePackProperty };
string request = TBase_Json.ToJson(obj);
string TempJson = HttpPostHelper.HttpPost(string.Format(initExecuteRequest, "http://" + serverInfo.ServerIp + ":" + serverInfo.ServerPort, "StartDataWhTask", ""), request);
}
else
{
EnqueueDataWh(dataWhtaskPack);
RegisterServiceStatus(serverInfo);
//任务忙等10秒
Thread.Sleep(10000);
}
}
}
//等待3秒
Thread.Sleep(3000);
}
catch (Exception err)
{
LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.SysLog, retObjs, "调度线程(出队)", err.ToString(), dt1, DateTime.Now, "QPCenterServices.ServiceEngine.QPCenterDispatchService.SyncCache");
}
}
}
九、状态模式
定义:允许一个对象在其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类
实例核心点:数据库分布式应用,根据数据库ID的状态值,读写不同的数据库
应用实例代码
/// <summary>
/// 执行SQL
/// </summary>
/// <param name="strTableSQL"></param>
/// <param name="DBID">数据库ID</param>
/// <returns></returns>
public static bool ExecuteSQL(string strTableSQL,string DBID)
{
DateTime dt1 = DateTime.Now;
try
{
LogMsgSendServer.LogMsgSend(strTableSQL, "Success");
TCustomConnection _Connection = null;
bool success = new bool();
if (TDataAccessFactory.Instance.Connection(TDataAccessFactory.Instance.DataSource.GetConnectionInfo(DBID), ref _Connection))
{
using (_Connection)
{
if (_Connection.Open())
{
success = _Connection.ExecuteSQL(strTableSQL);
}
}
}
LogMsgHelper.WriteLogsToQueue(LogLevel.INFO, SysType.Core, LogType.DataBaseLog, "", "数据执行成功" + strTableSQL, "", dt1, DateTime.Now, "QPCenterExpress.Data.Factory.TDataSqlHelper.ExecuteSQL");
return success;
}
catch (Exception ex)
{
LogMsgHelper.WriteLogsToQueue(LogLevel.ERROR, SysType.Core, LogType.DataBaseLog, strTableSQL, "数据库访问出错", ex.ToString(), dt1, DateTime.Now, "QPCenterExpress.Data.Factory.TDataSqlHelper.ExecuteSQL");
LogMsgSendServer.LogMsgSend(strTableSQL, "Fail");
throw ex;
}
}
十、发布订阅模式
定义:发布者与订阅者中间多一个“调度中心”。因此更解耦,所以常见系统中把调用的任务交给一个调度中心(中介),让调度中心去通知各个订阅者
实例核心:发布者推送信息,调度中心控制推给哪些订阅者,订阅者信息接收
应用实例代码:
如在KAFKA里的
生产者(即发布)
命令如下
bin/kafka-console-producer.sh --broker-list 192.168.183.129:9092,192.168.183.130:9092,192.168.183.131:9092 --topic hello
消费者(即订阅)
命令如下
bin/kafka-console-consumer.sh --bootstrap-server 192.168.183.129:9092,192.168.183.130:9092,192.168.183.131:9092 --topic hello