.Net中的设计模式——Strategy模式。Strategy模式与Delegate委托。

.Net中之设计模式——Strategy模式

Strategy模式是对算法的卷入。即使是一个测算行为,如果那个落实有那多样性,为直达易扩展的目的,我们啊起必要将该抽象出来,以接口的款型来定义。由于充分利用了面向对象的多态性,在调用该行为经常,其切实的贯彻是当运行期决定的。以税收计算也条例,假得税收政策分为个人所得税,和企业所得税。根据政策模式,将税收政策抽象为接口ITaxStrategy:

如出一辙、模式概述

public interface ITaxStrategy

“面向接口编程”是面向对象编程思想被极根本之一个原则。根据“封装变化”的法则,我们常将便于变动之组成部分开展抽象,定义为接口。对于调用者而言,只待理解接口的外部定义即可,具体的贯彻则毫不理会。在设计模式中,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模式

     double
Calculate(double income);

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);

public class PeronalTaxStrategy:ITaxStrategy

      // 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的兑现所代表,但这种规划思想依然是值得借鉴之。

{

      public
double Calculate(double income)

      {

           
//实现;

      }

}

public class
EnterpriseTaxStrategy:ITaxStrategy

{

      public
double Calculate(double income)

      {

            //实现;

      }

}

假设此时时有发生一个公家的近乎,提供税收的有关操作,其中便包括计算所得税的章程:

public class TaxOp

{

      private
ITaxStrategy strategy;

      public
TaxOp(ITaxStrategy strategy)

      {

           
this.strategy = strategy;

      }

      public
double GetTax(double income)

      {

            
return strategy.Calculate(income);

      }

}

客户端调用:

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));

}

}

眼看是同一栽典型的面向对象的设计思路。然而,对于有简的算法行为,我们为堪下delegate委托的方式,来促成上述的筹划,它虽然还近乎于面向过程的规划,但那扩展性同样灵活。如果算法的逻辑不复杂,且算法的落实处于某种待定的状态,也许下委托会比Strategy模式更便宜。

咱一样以上述的例子,只是用原来抽象出来的接口修改为委托:

public delegate double CalculateTax(double
income);

对个人所得税和企业所得税的贯彻,相应修改为:

public class Tax

{

      public
static double CalculatePersonalTax(double income)

      {

           
//实现;

      }

public static double CalculateEnterpriseTax(double
income)

      {

           
//实现;

      }

}

税收的公共类则改如下:

public class TaxOp

{

      private
CalculateTax calDel;

      public
TaxOp(Calculate calDel)

      {

           
this.calDel = calDel;

      }

      public
double GetTax(double income)

      {

            
return calDel(income);

      }

}

客户端的调用:

public class App

{

      public
static void Main(string[] args)

      {

           
TaxOp op = new TaxOp(new
CalculateTax(Tax.CalculatePersonalTax));

           
Console.WriteLine(“The Personal Tax is :{0}”,
op.GetTax(1000));

}

}

打马上简单独实现方案来拘禁,代码是相差无几的,但计划思想则迥然不同。它是面向对象和面向过程的别,前者是拿表现封装为目标,而后者则直指向章程进行操作,同时又利用delegate委托来实现扩大。个人看法,我或倾向被第一栽方案,但后者至少也供了一样种思路。尤有甚者,我们为可用委托理解也同样种植新鲜的抽象,因为其面目是函数指针,它意味着了平等丛函数,从而对有同等特性的一言一行进行了普遍意义的架空。也许,这样好有助于对信托的明。

 

相关文章

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注