.Net中的設計模式—Strategy模式(轉載)

一、模式概述

“面向接口編程”是面向對象編程思想中最重要的一個原則。根據“封裝變化”的原理,我們常常將易於變化的部分進行抽象,定義爲接口。對於調用者而言,只需要知道接口的外部定義即可,具體的實現則不用理會。在設計模式中,Strategy模式就是這樣的一個“面向接口編程”的最佳體現,它進行抽象的一部分是針對特定的“算法”,或者說是“策略”。
假設我們要開發一個稅務系統,那麼有關稅務的計算就會依照納稅人的不同而分爲個人所得稅和企業所得稅,而這兩種稅收類型依法應繳納的稅金在計算方式上是迥然不同的兩種策略。此時,我們就可以應用策略模式,將稅收策略抽象爲接口ITaxStrategy:
public interface ITaxStrategy
{
double Calculate(double income);
}
在對稅收計算策略完成了抽象後,就從設計上去除了模塊間存在的耦合,消除了變化可能會造成的未來系統的大規模修改,而所謂“面向接口編程”正是基於這樣的道理。
定義接口之後,各種稅收策略均實現該接口:
public class PeronalTaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{
//實現略;
}
}
public class EnterpriseTaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{
//實現略;
}
}
如果此時有一個公共的類,提供稅收的相關操作,其中就包括計算所得稅的方法:
public class TaxOp
{
private ITaxStrategy m_strategy;
public TaxOp(ITaxStrategy strategy)
{
this.m_strategy = strategy;
}
public double GetTax(double income)
{
return strategy.Calculate(income);
}
}
在這個類中,接收了一個ITaxStrategy類型的對象,由於該對象是一個接口類型,因此類TaxOp是與具體稅收策略無關的,它們之間因爲接口的引入而成爲了一個弱依賴的關係,如類圖所示:



如果客戶端要調用有關稅收的操作時,就可以根據納稅人的類型具體實例化稅收策略對象:
public class App
{
public static void Main(string[] args)
{
TaxOp op = new TaxOp(new PersonalTaxStrategy());
Console.WriteLine(“The Personal Tax is :{0}”, op.GetTax(1000));
}
}

二、.Net Framework中的Strategy模式

Stragety模式的應用極爲廣泛,在.Net Framework中自然不乏應用的例子。例如在.Net中,爲集合類型Array和ArrayList提供的排序功能,其實現中就利用了Strategy模式。它是對比較算法進行了封裝,定義了IComparer接口。實現IComparer接口的類,可以是順序,也可以是逆序的比較兩個對象的大小。
此外,在System.Configuration.Provider命名空間中,關於Provider的繼承體系下就引入了諸多Strategy模式的應用。在這個命名空間下,主要是定義了一個抽象類ProviderBase,它的定義較爲簡單,僅僅包括一個初始化的虛方法和幾個虛屬性,如下代碼:
public abstract class ProviderBase
{
// Methods
protected ProviderBase();
public virtual void Initialize(string name, NameValueCollection config);

// Properties
public virtual string Description { get; }
public virtual string Name { get; }

// Fields
private string _Description;
private bool _Initialized;
private string _name;
}
ProviderBase的派生類較多,包括有System.Configuration.ProtectedConfigurationProvider、System.Configuration.SettingProvider、System.Web.Security.RoleProvider、System.Web.Security.MembershipProvider等,不過這些派生子類都是抽象類,它們又自有各自的繼承體系,且同時具備了Strategy模式的特徵。以RoleProvider爲例,首先,我們看看RoleProvider在.Net Framework中的定義:
public abstract class RoleProvider : ProviderBase
{
// Methods
protected RoleProvider();
public abstract void AddUsersToRoles(string[] usernames, string[] roleNames);
public abstract void CreateRole(string roleName);
public abstract bool DeleteRole(string roleName, bool throwOnPopulatedRole);
public abstract string[] FindUsersInRole(string roleName, string usernameToMatch);
public abstract string[] GetAllRoles();
public abstract string[] GetRolesForUser(string username);
public abstract string[] GetUsersInRole(string roleName);
public abstract bool IsUserInRole(string username, string roleName);
public abstract void RemoveUsersFromRoles(string[] usernames, string[] roleNames);
public abstract bool RoleExists(string roleName);

// Properties
public abstract string ApplicationName { get; set; }
}
在RoleProvider抽象類中,沒有具體的實現,均爲抽象方法,此時的抽象類其實已與接口無異(注:事實上,在WebLogic中,在對角色管理的API中,就將RoleProvider定義爲接口)。爲了便於理解這裏的設計思想,我們對RoleProvider類進行簡化,僅關注該類的CreateRole()抽象方法。
發佈了30 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章