Net中的设计情势

.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

发表评论

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