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

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


2008-04-10 来自:java060515


一、模式概述

“面向接口编程”是面向对象编程思想中最重要的一个原则。根据“封装变化”的原理,我们常常将易于变化的部分进行抽象,定义为接口。对于调用者而言,只需要知道接口的外部定义即可,具体的实现则不用理会。在设计模式中,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是与具体税收策略无关的,它们之间因为接口的引入而成为了一个弱依赖的关系,如类图所示:



如果客户端要调用有关税收的操作时,就可以根据纳税人的类型具体实例化税收策略对象:
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()抽象方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值