C#項目中常用到的設計模式

来源:http://www.cnblogs.com/VectorZhang/archive/2016/06/02/5554388.html
-Advertisement-
Play Games

1. 引言 一個項目的通常都是從Demo開始,不斷為項目添加新的功能以及重構,也許剛開始的時候代碼顯得非常凌亂,毫無設計可言。但是隨著項目的迭代,往往需要將很多相同功能的代碼抽取出來,這也是設計模式的開始。熟練運用設計模式應該是每一個軟體開發人員的必備技能。今天給大家介紹幾個常用的設計模式。 2. ... ...


1. 引言

一個項目的通常都是從Demo開始,不斷為項目添加新的功能以及重構,也許剛開始的時候代碼顯得非常凌亂,毫無設計可言。但是隨著項目的迭代,往往需要將很多相同功能的代碼抽取出來,這也是設計模式的開始。熟練運用設計模式應該是每一個軟體開發人員的必備技能。今天給大家介紹幾個常用的設計模式。

 

2. 單例模式

單例模式恐怕是很多開發人員最先接觸到的模式之一,可以認為就是一個全局變數。它的初始化過程無非就是一開始就new 一個instance,或者惰性初始化等需要用到的時候new 一個instance。這裡需要註意的是在多線程情況下new一個instance。通常加上lock 可以解決問題。這裡我們利用C# 的系統函數 Interlocked.CompareExchange

    internal class SingletonOne
    {
        private static SingletonOne _singleton;
        private SingletonOne()
        {
        }

        public static SingletonOne Instance
        {
            get
            {
                if (_singleton == null)
                {
                    Interlocked.CompareExchange(ref _singleton, new SingletonOne(), null);
                }

                return _singleton;
            }
        }
    }

 

3. 迭代器模式

迭代器模式也是用的比較多的一種,通常見於C#的內置容器數據結構 List,Stack等等,為了便於遍歷容器內元素。這裡給出一個簡單版的Stack實現

    internal class Stack<T> : IEnumerable<T>, IEnumerable
    {
        private T[] _array;
        private int _index;
        private const int DefaultSize = 4;

        public Stack(int size)
        {
            var sized = size > 0 ? size : DefaultSize;
            this._array = new T[sized];
            this._index = 0;
        }

        public int Count
        {
            get { return this._index; }
        }

        public Stack(IEnumerable<T> data) : this(0)
        {
            var enumrator = data.GetEnumerator();
            while (enumrator.MoveNext())
            {
                var item = enumrator.Current;
                this.Push(item);
            }
        }

        public void Push(T item)
        {
            if (this._index < this._array.Length)
            {
                this._array[this._index++] = item;
            }
            else
            {
                var newLength = this._array.Length << 1;
                T[] newArray = new T[newLength];
                Array.Copy(this._array, newArray, this.Count);

                this._array = newArray;
                this.Push(item);
            }
        }

        public T Pop()
        {
            if (this.Count <= 0)
            {
                throw new ArgumentOutOfRangeException("pop");
            }
            else
            {
                this._array[this._index] = default(T);
                return this._array[--this._index];
            }
        }

        public T Get(int index)
        {
            if (this.Count <= index)
            {
                throw new ArgumentOutOfRangeException("Get");
            }
            else
            {
                return this._array[index];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new StackEnumerator<T>(this);
        }
    }

Stack 的 迭代器內部實現:

    internal class StackEnumerator<T> : IEnumerator<T> , IEnumerator
    {
        private Stack<T> _stack;
        private int _index;

        public StackEnumerator(Stack<T> stack)
        {
            this._stack = stack;
            this._index = -1;
        }

        public bool MoveNext()
        {
            this._index++;
            return this._index < this._stack.Count;
        }

        public void Reset()
        {
            this._index = -1;
        }

        object  IEnumerator.Current 
        {
            get { return this.Current; } 
        }

        public T Current
        {
            get { return this._stack.Get(this._index); }
        }

        public void Dispose()
        {
            this._stack = null;
        }
    }

 

4 工廠模式

工廠模式細分的話有簡單工廠模式、抽象工廠模式等。它最核心的就是如何通過 Factory new 一個 對象出來。在ASP.NET MVC 消息處理實現過程中工廠模式運用的非常多。比如

在MVC中處理一個Request,其實就是調用Controller下的一個Action,這就需要從Url 和Route 中反射出Controller對象,內部由ControllerFactory創建。

image

它的預設實現是:DefaultControllerFactory

image

另一個例子是ValueProviderFactory,它使得Controller 下的Action 能夠接收到前端傳回來的數據並實現模型綁定,是典型的抽象工廠實現。

image

 

5. 訂閱模式

訂閱模式在某些項目運用比較多,比如 Knockout 整個項目就是一個大的訂閱模式的實現,但是它是用javascript編寫的。還有像微博、微信公眾號等等訂閱模式通常少不了。

通常可以定義介面:

    internal interface ISubject
    {
        IEnumerable<IObserver> Observers { get; } 
        void Notify();
        void AddObserver(IObserver observer);
        void RemoveObserver(IObserver observer);
    }

    internal interface IObserver
    {
        void ReceiveSubject(ISubject subject);
    }

實現:

    internal class AritcleObserver : IObserver
    {
        public void ReceiveSubject(ISubject subject)
        {
            // receive the subject
        }
    }

    class WeChatArticle : ISubject
    {
        private ICollection<IObserver> _observers;
        private string _name;

        public WeChatArticle(string name)
        {
            this._name = name;
            this._observers = new List<IObserver>();
        }

        public IEnumerable<IObserver> Observers
        {
            get { return this._observers; }
        }

        public void Notify()
        {
            foreach (IObserver observer in this._observers)
            {
                observer.ReceiveSubject(this);
            }
        }

        public void AddObserver(IObserver observer)
        {
            this._observers.Add(observer);
        }

        public void RemoveObserver(IObserver observer)
        {
            this._observers.Remove(observer);
        }
    }

 

6.  責任鏈模式

責任鏈模式沒有像工廠模式那樣被人熟悉,在ASP.NET WebApi 中有一個非常典型的實現 就是WebApi的消息處理管道HttpMessageHandler

image

這裡給一個簡單的模擬

    class DataRequest
    {
        public string FileName { get; set; }
    }

    class DataResponse
    {
        public string Error { get; set; }
        public string Data { get; set; }
    }

    internal abstract class RequestHandler
    {
        public RequestHandler NextHandler { get; set; }
        public abstract DataResponse Process(DataRequest request);
    }

    class ReadRequestHandler : RequestHandler
    {
        public override DataResponse Process(DataRequest request)
        {
            return new DataResponse()
            {
                Data = File.ReadAllText(request.FileName)
            };
        }
    }

    class ExistsRequestHandler : RequestHandler
    {
        public override DataResponse Process(DataRequest request)
        {
            if (File.Exists(request.FileName))
            {
                return this.NextHandler.Process(request);
            }
            else
            {
                return new DataResponse()
                {
                    Error = "no exists"
                };
            }
        }
    }

 

7. 組合模式

組合模式是使得單個對象和組合對象有一致的行為,一致的行為可以理解為擁有同一個介面,比如圖形顯示

    class ControlContext
    {
    }

    internal interface IControl
    {
        void Draw(ControlContext context);
    }

    class Line : IControl
    {
        public void Draw(ControlContext context)
        {
        }
    }

    class Circle : IControl
    {
        public void Draw(ControlContext context)
        {}
    }

    class CompositeControl : IControl
    {
        private List<IControl> controls;

        public CompositeControl(IList<IControl> cons)
        {
            this.controls = new List<IControl>(cons);
        }

        public void Draw(ControlContext context)
        {
            this.controls.ForEach(c => c.Draw(context));
        }

        public void Add(IControl control)
        {
            this.controls.Add(control);
        }
    }

 

8. 總結

市場上有很多關於設計模式的書,但是基本的設計模式大概有20多種,本文給大家介紹了幾種項目中常見的設計模式,其實有些設計模式在實際項目已經不知不覺用起來了。

以後再給大家介紹其他的幾種設計模式。

 

歡迎訪問我的個人主頁 51zhang.net  網站還在不斷開發中…..


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我的機子炸了,然後我就得重新裝我的虛擬機,再然後我就想去弄好我的共用文件夾安裝vmtools,安裝的時候出現了一個問題,我忘記以前是怎麼解決的,又困擾了我好久 Searching for a valid kernel header path... The path "" is not a valid ...
  • 如何一步步點亮LED 註:實驗是基於s5pv210的板子,這篇筆記參考自《朱老師物聯網大講堂》朱老師隨堂筆記 文中提到的手冊下載鏈接:(https://yunpan.cn/OcSz7Yh35ISJK7 訪問密碼 6665;https://yunpan.cn/OcSz7SzsfS7a6p 訪問密碼 1 ...
  • 我們經常在Linux下可以看到inode,都不知道是什麼東東,那麼我們現在來慢慢瞭解下。 一、inode是什麼? 理解inode,要從文件儲存說起。 文件儲存在硬碟上,硬碟的最小存儲單位叫做"扇區"(Sector)。每個扇區儲存512位元組(相當於0.5KB)。 操作系統讀取硬碟的時候,不會一個個扇區 ...
  • 創建基本的鏈接和URL<!--?xml:namespace prefix = "o" ns = "urn:schemas-microsoft-com:office:office" /--> 在我們介紹鏈接或URL之前先做一些準備,我們這部分要介紹的知識將要使用的項目就是之前建立的HelperMeth ...
  • 0 概述 所謂同步,就是給多個線程規定一個執行的順序(或稱為時序),要求某個線程先執行完一段代碼後,另一個線程才能開始執行。 第一種情況:多個線程訪問同一個變數: 1. 一個線程寫,其它線程讀:這種情況不存在同步問題,因為只有一個線程在改變記憶體中的變數,記憶體中的變數在任意時刻都有一個確定的值; 2. ...
  • ...
  • 主要代碼,請根據實際情況修改。 Response.Write("<div id='mydiv' >"); Response.Write("_"); Response.Write("</div>"); Response.Write("<script>mydiv.innerText = '';</scr ...
  • 相比輔助器方法,模板輔助器方法更智能一些,它們可以指定想要顯示的屬性,而讓MVC框架去判斷應該使用什麼樣的HTML元素。只是,需要一些初期關註才能建立起來,但畢竟是一種顯示數據的更為靈活的方式。 這裡打算繼續使用介紹輔助器方法時使用的項目,但是,CreatePerson.cshtml視圖在之前的輔助 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...