.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的贯彻所取代,但那种规划思想依旧是值得借鉴的。

相关文章