1. 程式人生 > >C# 項目中常用到的設計模式

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

pos .com size href int wid compare copy wechat

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創建。

技術分享圖片

它的默認實現是:DefaultControllerFactory

技術分享圖片

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

技術分享圖片

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

技術分享圖片

這裏給一個簡單的模擬

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多種,本文給大家介紹了幾種項目中常見的設計模式,其實有些設計模式在實際項目已經不知不覺用起來了。

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

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