程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 優雅就一個字——設計模式之數據上傳接口

優雅就一個字——設計模式之數據上傳接口

編輯:C#入門知識

在網上看到很多關於設計模式的文章。但是基本都是單獨講解某一個設計模式的應用場景和設計思路。可是真實的項目中,可能僅僅只按照書上的某種設計模式就能寫出優雅的代碼嗎?我覺得是不可能的。我這篇文章希望跟大家分享的是我思考的過程,而非結果。首先,應該對書上的20多種的設計模式有了解,大概清楚它們都是怎麼樣一個設計思路。建議有想學習設計模式的Friends還是買本紙質書系統的學習。下面,我給出一個真實的項目來引出我對這個項目的思考。第一次寫博客分享我的思路,在加上我的思維有些女性思維,是跳躍性的。可能有些表達不是很清楚。望大家見諒。

    • 看到這流程圖,首先在我腦海裡的就是這是由一個一個小方塊組合起來的組合體。我們先不管具體代碼該怎麼寫,類怎麼設計。只知道這是一個組合體。會有很多類。說到組合,我們是否可以聯想到這應該是一個結構型的設計。這個組合體是由這些小方塊代表的類按照某種結構組合起來的。結構型的設計模式有哪些,大家腦海裡應該會有個輪廓了。
    • 又看到每一個小方塊有分支,2個分支,分別代表正確的時的下一個流程和不正確時的下一個流程。這是不是意味著,我的方法會一層一層往下調用,直到最後一個小方塊對象的下個流程對象為null時停止。想到這,我腦海裡想到了裝飾者模式和職責鏈模式。可是裝飾者模式沒有判斷條件,它只是按照你組合的順序,依次往下調用。那麼這是不是更加符合職責鏈模式呢?咋一看很像,職責鏈模式是在一個流程內,沒有處理的權限就往後傳遞,有處理權限就跳出方法鏈。跟我們的2個分支有些不同。我們的需求是要既有權限處理往後傳遞,沒有權限也要往後傳遞。想到這,我們就清楚了,在小方塊所代表的類裡,應當有兩個屬性,一個是判斷條件為True時的下一流程對象,另一個是判斷條件為False時下一流程對象。這樣,小方塊類的類結構裡就有了兩個屬性了。
    • 接著又想,每個小方塊代表的類,所執行的具體業務邏輯不一樣,所以,我們在接口裡是否應該有個方法可供子類重寫呢?這樣一來,每個小方塊所代表的類都有了自己的業務邏輯。但是,那在什麼地方調用下個流程的業務邏輯呢?如果放在單獨的每個小方塊所代表的類中,那豈不是,我們在每一個小方塊類中都要寫一些重復的調用下個流程的代碼呢?這樣就不夠優雅了。所以,我想要調用過程在父級類裡實現。為了實現小方塊類的多態和調用下個流程的代碼復用,就有了一個能夠有方法實現的類。這個類又必須包含抽象方法。那所有流程的抽象基類出來了。這個抽象類實現之前定義的接口。其實這個接口要不要都無所謂啦,不過好像每個設計模式都是從接口開始,那麼就保留一個接口吧。
    • 抽象類有了,每個子類重寫的業務邏輯方法也有了。接下來,就是寫調用被重寫的業務邏輯的方法了。此處,大家應該可以想到是一個模板方法吧。但是,我們這裡有兩個分支,具體調用哪一個分支是由當前的小方塊類決定的。這樣一想,那這個調用下個小方塊類的業務邏輯方法的代碼豈不是只能寫在具體的每個小方塊類裡了。這樣不是很麻煩嗎?我們要想一個辦法,將這個過程放在抽象類裡解決。鑒於最多也就兩個分支,不是正就是反。那麼我們是否可以通過在抽象類裡設置一個屬性,來標識下一流程具體調用的是哪一個分支呢?所以我們抽象類裡又有了一個屬性。這個屬性是要被子類在業務邏輯方法中重新賦值的。
    • 當某些業務處理完之後,可能就直接要結束整個流程,比如說,如果我第一步驗證沒通過,那麼後面的流程都不能被執行。所以,我們要能夠隨時退出整個流程。這樣,我們跟上面決定調用哪個分支的設計思路一致,加一個屬性,來標識說是否要結束整個流程。可供子類重新賦值。在父類的調用下一個流程的方法中做判斷。
  • 那現在我們的抽象類裡就有了3個屬性,2個方法。
  • 然後,總有參數要傳遞到每一個小方塊類的業務邏輯方法中吧。那麼我們這裡就將所有參數封裝成一個數據實體類。依次傳遞到每個小方塊類的業務邏輯方法中。大概思路就說到這吧。還有一些業務需求沒有講到,那在代碼裡都有體現。先上代碼吧。

 

    /// <summary>
    /// 處理流程基類
    /// </summary>
    public abstract class ProcessFlowBase : IProcessFlow
    {
        protected ProcessFlowBase(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase), ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))
        {
            this.NextProcessFlowWhenRight = processFlowWhenRight;
            this.NextProcessFlowWhenWrong = processFlowWhenWrong;
            this.IsRight = true;
            this.IsEnd = false;
        }

        protected IDbConnection DbConnection { get; set; }

        protected IDbCommand DbCommand { get; set; }

        protected IDbTransaction DbTransaction { private get; set; }

        /// <summary>
        /// 當前流程是否處理通過
        /// </summary>
        private bool IsRight { get; set; }

        /// <summary>
        /// 流程是否結束
        /// </summary>
        private bool IsEnd { get; set; }

        /// <summary>
        /// 下一個流程,當流程處理操作通過的時候
        /// </summary>
        private ProcessFlowBase NextProcessFlowWhenRight { set; get; }

        /// <summary>
        /// 下一個流程,當流程處理操作不通過的時候
        /// </summary>
        private ProcessFlowBase NextProcessFlowWhenWrong { get; set; }

        /// <summary>
        /// 處理
        /// </summary>
        /// <param name="dataContext"></param>
        public void Process(DataContext dataContext)
        {
            this.ProcessTemplate(dataContext);
            this.RecordLog(dataContext);
            if (this.IsEnd) return;
            if (this.IsRight)
            {
                if (this.NextProcessFlowWhenRight == default(ProcessFlowBase)) return;
                this.NextProcessFlowWhenRight.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);
                this.NextProcessFlowWhenRight.Process(dataContext);
            }
            else
            {
                if (this.NextProcessFlowWhenWrong == default(ProcessFlowBase)) return;
                this.NextProcessFlowWhenWrong.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);
                this.NextProcessFlowWhenWrong.Process(dataContext);
            }
        }

        /// <summary>
        /// 流程處理模板方法,供子類實現
        /// </summary>
        /// <param name="dataContext"></param>
        protected abstract void ProcessTemplate(DataContext dataContext);

        /// <summary>
        /// 記錄日志,供子類實現
        /// </summary>
        /// <param name="dataContext"></param>
        protected virtual void RecordLog(DataContext dataContext)
        {
            LogHelper.Record(dataContext);
        }

        /// <summary>
        /// 結束本次流程
        /// </summary>
        protected void EndProcessFlow()
        {
            this.IsEnd = true;
        }

        /// <summary>
        /// 確定下一流程,後續候選流程名單在調用構造函數的時候已經初始化好
        /// </summary>
        /// <param name="rightFlowOrWrongFlow"></param>
        protected void SetNextFlow(RightFlowOrWrongFlow rightFlowOrWrongFlow)
        {
            this.IsRight = rightFlowOrWrongFlow == RightFlowOrWrongFlow.Right;
        }

        /// <summary>
        /// 回滾操作流程
        /// </summary>
        protected void RollBackProcessFlow()
        {
            this.DbTransaction.Rollback();
            this.DbConnection.Close();
        }

        /// <summary>
        /// 提交事物操作
        /// </summary>
        protected void CommitProcessFlow()
        {
            this.DbTransaction.Commit();
            this.DbConnection.Close();
        }

        /// <summary>
        /// 設置下一流程單例屬性
        /// </summary>
        /// <param name="param"></param>
        private void SetParameters(params object[] param)
        {
            var dbConnection = param[0] as IDbConnection;
            var dbCommand = param[1] as IDbCommand;
            var dbTransaction = param[2] as IDbTransaction;
            this.DbConnection = dbConnection;
            this.DbCommand = dbCommand;
            this.DbTransaction = dbTransaction;
        }
    }

 

 

    /// <summary>
    /// 檢驗授權碼流程,此流程應當作為所有業務流程的入口流程。會在此類中做一些特別的處理
    /// </summary>
    public class CheckToken : ProcessFlowBase
    {
        public CheckToken(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase),
            ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))
            : base(processFlowWhenRight, processFlowWhenWrong)
        {
            //這個流程作為所有業務處理的入口流程,所以,我在這裡要寫入一段初始化流程事務對象的代碼,僅執行一次
            base.DbConnection = LogHelper.CreateDbConnection();
            base.DbConnection.Open();
            base.DbCommand = base.DbConnection.CreateCommand();
            base.DbTransaction = base.DbConnection.BeginTransaction();
        }

        protected override void ProcessTemplate(DataContext dataContext)
        {
            //查詢授權碼是否存在
            var sbSelectSql = new StringBuilder();
            sbSelectSql.AppendFormat(@"Some SQL Here", dataContext.AuthCode, dataContext.PartCode);
            dataContext.SQL = base.DbCommand.CommandText = sbSelectSql.ToString();
            var any = Convert.ToInt32(base.DbCommand.ExecuteScalar());
            if (any > 0)
            {
                base.SetNextFlow(RightFlowOrWrongFlow.Right);
            }
            else
            {
                dataContext.StatusCode = "1001";
                base.RollBackProcessFlow();
                base.EndProcessFlow();
            }
        }

        /// <summary>
        /// 記錄日志
        /// </summary>
        /// <param name="dataContext"></param>
        protected override void RecordLog(DataContext dataContext)
        {
        }
    }
 
    /// <summary>
    /// 讀取包含數據的XML文件
    /// </summary>
    public class LoadXElement : ProcessFlowBase
    {
        public LoadXElement(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase), ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))
            : base(processFlowWhenRight, processFlowWhenWrong) { }

        protected override void ProcessTemplate(DataContext dataContext)
        {
            try
            {
                using (var memoryStream = new MemoryStream(dataContext.Buffer))
                {
                    dataContext.DataXElement = XElement.Load(memoryStream);
                }
                var folderPath = HttpContext.Current.Server.MapPath("/ModuleSources/FileStore/AppFile/TunnelMeasure/Surface");
                if (!Directory.Exists(folderPath))
                    Directory.CreateDirectory(folderPath);
                var xmlPath =
                    string.Format(
                        folderPath + "/{0}_01_{1}.xml",
                        dataContext.PartCode, DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"));
                using (var fileStream = new FileStream(xmlPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    dataContext.DataXElement.Save(fileStream);
                }
                dataContext.XMLPath = xmlPath;
            }
            catch (Exception)
            {
                //讀取文件流失敗
                dataContext.StatusCode = "1002";
                base.RollBackProcessFlow();
                base.EndProcessFlow();
                return;
            }
            base.SetNextFlow(RightFlowOrWrongFlow.Right);
        }
    }
    
  • 可是當我讀了《市場的力量》之後,想法有些許的改變了。有個例子。中國古代一發生天災人禍時,就鬧饑荒。百姓餓死的很多。有些黑心的商人就囤積居奇。朝廷為了穩定糧價,穩住民生。就機。這時的中國政府就是個反面例子。那還有一個例子就是二戰後的德國,民不聊生,人民連維持基本生命需求的食物都不能滿足。結果導致黑市橫行。政府怎麼管都無法消滅黑市。這時一個聰明的辦法出來了。美國政府跟黑市一起搞。那市民還是覺得政府會更可靠吧。黑市逐漸的也就消亡了。美國的政治智慧還是很偉大的。核心思想就是妥協,也就是保持平衡。折射到中國房地產,也許先進的中國房價還不夠高。政府如何調控,房價都不會有明顯的下降。即便是房價下來了,那商人們會不會在其他地方增加隱形收費來彌補房價下跌的這個缺口呢?我想會的。也許中國房價在高些,高得大部分人買不起了。市場機制就展現出他的力量了。市場倒逼價格下降,服務優化。還是多看歷史吧。也許我的見解也很片面。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved