一個項目的通常都是從Demo開始,不斷為項目添加新的功能以及重構,也許剛開始的時候代碼顯得非常凌亂,毫無設計可言。但是隨著項目的迭代,往往需要將很多相同功能的代碼抽取出來,這也是設計模式的開始。熟練運用設計模式應該是每一個軟件開發人員的必備技能。今天給大家介紹幾個常用的設計模式。
單例模式恐怕是很多開發人員最先接觸到的模式之一,可以認為就是一個全局變量。它的初始化過程無非就是一開始就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;
}
}
}
迭代器模式也是用的比較多的一種,通常見於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;
}
}
工廠模式細分的話有簡單工廠模式、抽象工廠模式等。它最核心的就是如何通過 Factory new 一個 對象出來。在ASP.NET MVC 消息處理實現過程中工廠模式運用的非常多。比如
在MVC中處理一個Request,其實就是調用Controller下的一個Action,這就需要從Url 和Route 中反射出Controller對象,內部由ControllerFactory創建。

它的默認實現是:DefaultControllerFactory

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

訂閱模式在某些項目運用比較多,比如 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);
}
}
責任鏈模式沒有像工廠模式那樣被人熟悉,在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"
};
}
}
}
組合模式是使得單個對象和組合對象有一致的行為,一致的行為可以理解為擁有同一個接口,比如圖形顯示
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);
}
}
市場上有很多關於設計模式的書,但是基本的設計模式大概有20多種,本文給大家介紹了幾種項目中常見的設計模式,其實有些設計模式在實際項目已經不知不覺用起來了。
以後再給大家介紹其他的幾種設計模式。