.Net中的设计格局——Strategy形式

.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是与实际税收政策无关的,它们中间因为接口的引入而成为了一个弱看重的关系,如类图所示:
 图片 1
倘诺客户端要调用有关税收的操作时,就足以依照纳税人的项目具体实例化税收政策对象:
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()抽象方法。
心想事成RoleProvider抽象类的品类比较多,例如AuthorizationStoreRoleProvider、SqlRoleProvider、WindowsTokenRoleProvider等等。因而,最终的兑现类图应该如下:
 图片 2
子类均重写了父类RoleProvider的架空方法,例如SqlRoleProvider:
public class SqlRoleProvider:RoleProvider
{
 public override void CreateRole(string roleName)
 {
  //实现略;
 }
}
在ASP.NET中会用到RoleProvider,经常是在web.config配置文件对其展开配置,例如在RoleManager节中配备RoleProvider:
<roleManager defaultProvider=”SqlProvider” enabled=”true”>
    <providers>
       <add  name=”SqlProvider”
        type=”System.Web.Security.SqlRoleProvider”
        connectionStringName=”SqlServices”
        applicationName=”PatternsSample” />
    </providers>
</roleManager>
在配置文件中,.Net内部的拍卖时,要求providers的档次必须是RoleProvider类型,然后经过设置type的值,使其与实际的RoleProvider举办绑定。这里的惩处措施明确使用了Dependency
Injection(倚重注入)技术,利用反射技术将SqlRoleProvider对象sqlProvider注入,这样就制止了对SqlRoleProvider具体目的的创办,解除了调用者与它里面的偶合。当然在安排文件中,RoleProvider还需与Membership配合使用,但这不是这里所要关注的基本点,由此不再详细讲解。
与RoleProvider相同的统筹艺术,在.Net
Framework中,MemberShipProvider同样利用了Strategy情势,如下图所示的宏图布局:
 图片 3
常用的是现实类SqlMembershipProvider,它为SQL
Server提供了Membership的管制。假使要为Membership提供对Oracle数据库的补助,大家得以自定义一个类继承MembershipProvider:
public class OracleMembershipProvider:MembershipProvider
{
 //实现略;
}
在.Net
Framework中,还有一个第一名的Strategy形式的施用,就是接口IConfigurationSectionHandler:
public interface IConfigurationSectionHandler
{     
      object Create(object parent, object configContext, XmlNode
section);
}
该接口中包含的法门唯有一个,就是Create()方法,我们可以通晓为创建配置节的一个算法,而落实该接口的类包括有DictionarySectionHandler、IgnoreSectionHandler、NameValueSectionHandler等等,分别对应各类配置节的开创项目。其余,我们还足以友善定义一个类,来兑现该接口,例如:
public class CustomHandler : IConfigurationSectionHandler
{
    public object Create(object parent, object configContext, XmlNode
section)
    {
       //实现略;
    }
}
从类图中,大家得以看看,它那多少个适合Strategy形式的性状:
 图片 4
即使在.Net2.0中,IConfigurationSectionHandler类型的目的已经被ObsoleteAttribute设置为撤废,而被ConfigurationSection的贯彻所替代,但那种计划思想依然是值得借鉴的。

相关文章