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

发表评论

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