左右逢源:策略模式
策略模式:它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的用户。
举一个示例来说:一个代理机票系统,普通用户和vip用户都可以有三种预定和支付方式。按照普通的编程思路,用工厂方法或者简单工厂,在两种用户的对应类里添加设置用户预定和支付的方法就可以了,这样确实也可以解决问题。但是,如果我们的系统需求发生改变(这个经常吧?!),比如说支付和预定方式都增加了,我们的工厂就要相应发生改变,以致代码需要重新编译部署,这不是最好的处理方式。其实这里支付和预定方式都是对应于具体的某种算法,所有算法各自完成的都是相同的工作,只是实现不同,面对算法的变动,剥离出变化点,我们就会想到策略模式。好了,code is cheap.上代码了。
类图:
![](https://images.cnblogs.com/cnblogs_com/wjfluisfigo/Strategy.jpg)
代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace StrategyPattern
{
/// <summary>
/// 预订方式
/// </summary>
public enum OrderType
{
Online, // 在线预定
Telephone, //电话预订
Counter //直接柜台预订
}
/// <summary>
/// 支付方式
/// </summary>
public enum PayType
{
Electronic, //网上银行
VirtualMoney,//虚拟货币
Cash //现金
}
public interface IOrder
{
bool AddOrder();
}
public class OnlineOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Online order.");
return true;
}
}
public class TelephoneOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Telephone order.");
return true;
}
}
public class CounterOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Counter order.");
return true;
}
}
public interface IPay
{
bool Pay();
}
public class ElectronicPay : IPay
{
public bool Pay()
{
Console.WriteLine("Electronic Pay.");
return true;
}
}
public class VirtualMoneyPay : IPay
{
public bool Pay()
{
Console.WriteLine("VirtualMoney Pay.");
return true;
}
}
public class CashPay : IPay
{
public bool Pay()
{
Console.WriteLine("Cash Pay.");
return true;
}
}
/* 策略模式 */
public abstract class Customer
{
private string name;
public Customer(string name)
{
this.name = name;
}
protected IOrder tmpOrder;
protected IPay tmpPay;
public void SetOrderType(IOrder order)
{
this.tmpOrder = order;
}
public void SetPayType(IPay pay)
{
this.tmpPay = pay;
}
public void BeginOperation() //这个可以当作简单的模板方法模式应用
{
tmpOrder.AddOrder();
tmpPay.Pay();
}
}
public class NormalUser : Customer
{
public NormalUser(string name)
: base(name)
{
base.tmpOrder = OrderSimpleFactory.CreateOrderType(OrderType.Counter); //普通客户,默认预订方式:柜台预订,支付方式:现金
base.tmpPay = PaySimpleFactory.CreatePayType(PayType.Cash);
}
public new void BeginOperation()
{
base.BeginOperation();
}
}
public class VipUser : Customer
{
public VipUser(string name)
: base(name)
{
base.tmpOrder = OrderSimpleFactory.CreateOrderType(OrderType.Online); //vip客户,默认预订方式:在线预定,支付方式:虚拟货币
base.tmpPay = PaySimpleFactory.CreatePayType(PayType.VirtualMoney);
}
public new void BeginOperation()
{
base.BeginOperation();
}
}
/*简单工厂模式*/
public class OrderSimpleFactory
{
private static IOrder order = null;
public static IOrder CreateOrderType(OrderType oType)
{
switch (oType)
{
default:
break;
case OrderType.Online:
order = new OnlineOrder();
break;
case OrderType.Telephone:
order = new TelephoneOrder();
break;
case OrderType.Counter:
order = new CounterOrder();
break;
}
return order;
}
}
/*简单工厂模式*/
public class PaySimpleFactory
{
private static IPay pay = null;
public static IPay CreatePayType(PayType pType)
{
switch (pType)
{
default:
break;
case PayType.Electronic:
pay = new ElectronicPay();
break;
case PayType.VirtualMoney:
pay = new VirtualMoneyPay();
break;
case PayType.Cash:
pay = new CashPay();
break;
}
return pay;
}
}
public class Program
{
static void Main(string[] args)
{
NormalUser nu = new NormalUser("jeff");
VipUser vu = new VipUser("Jeff Wong");
nu.BeginOperation(); //默认预订和支付方式
Console.WriteLine("---------------------------------------------------------------------------");
vu.BeginOperation(); //默认预订和支付方式
Console.WriteLine("---------------------------------------------------------------------------");
nu.SetOrderType(new TelephoneOrder());
nu.SetPayType(new VirtualMoneyPay());
//普通用户 更改预订方式和支付方式
vu.SetOrderType(new OnlineOrder());
vu.SetPayType(new ElectronicPay());
//VIP用户 更改预订方式和支付方式
nu.BeginOperation();
Console.WriteLine("---------------------------------------------------------------------------");
vu.BeginOperation();
Console.Read();
}
}
}
举一个示例来说:一个代理机票系统,普通用户和vip用户都可以有三种预定和支付方式。按照普通的编程思路,用工厂方法或者简单工厂,在两种用户的对应类里添加设置用户预定和支付的方法就可以了,这样确实也可以解决问题。但是,如果我们的系统需求发生改变(这个经常吧?!),比如说支付和预定方式都增加了,我们的工厂就要相应发生改变,以致代码需要重新编译部署,这不是最好的处理方式。其实这里支付和预定方式都是对应于具体的某种算法,所有算法各自完成的都是相同的工作,只是实现不同,面对算法的变动,剥离出变化点,我们就会想到策略模式。好了,code is cheap.上代码了。
类图:
![](https://images.cnblogs.com/cnblogs_com/wjfluisfigo/Strategy.jpg)
代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace StrategyPattern
{
/// <summary>
/// 预订方式
/// </summary>
public enum OrderType
{
Online, // 在线预定
Telephone, //电话预订
Counter //直接柜台预订
}
/// <summary>
/// 支付方式
/// </summary>
public enum PayType
{
Electronic, //网上银行
VirtualMoney,//虚拟货币
Cash //现金
}
public interface IOrder
{
bool AddOrder();
}
public class OnlineOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Online order.");
return true;
}
}
public class TelephoneOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Telephone order.");
return true;
}
}
public class CounterOrder : IOrder
{
public bool AddOrder()
{
Console.WriteLine("Counter order.");
return true;
}
}
public interface IPay
{
bool Pay();
}
public class ElectronicPay : IPay
{
public bool Pay()
{
Console.WriteLine("Electronic Pay.");
return true;
}
}
public class VirtualMoneyPay : IPay
{
public bool Pay()
{
Console.WriteLine("VirtualMoney Pay.");
return true;
}
}
public class CashPay : IPay
{
public bool Pay()
{
Console.WriteLine("Cash Pay.");
return true;
}
}
/* 策略模式 */
public abstract class Customer
{
private string name;
public Customer(string name)
{
this.name = name;
}
protected IOrder tmpOrder;
protected IPay tmpPay;
public void SetOrderType(IOrder order)
{
this.tmpOrder = order;
}
public void SetPayType(IPay pay)
{
this.tmpPay = pay;
}
public void BeginOperation() //这个可以当作简单的模板方法模式应用
{
tmpOrder.AddOrder();
tmpPay.Pay();
}
}
public class NormalUser : Customer
{
public NormalUser(string name)
: base(name)
{
base.tmpOrder = OrderSimpleFactory.CreateOrderType(OrderType.Counter); //普通客户,默认预订方式:柜台预订,支付方式:现金
base.tmpPay = PaySimpleFactory.CreatePayType(PayType.Cash);
}
public new void BeginOperation()
{
base.BeginOperation();
}
}
public class VipUser : Customer
{
public VipUser(string name)
: base(name)
{
base.tmpOrder = OrderSimpleFactory.CreateOrderType(OrderType.Online); //vip客户,默认预订方式:在线预定,支付方式:虚拟货币
base.tmpPay = PaySimpleFactory.CreatePayType(PayType.VirtualMoney);
}
public new void BeginOperation()
{
base.BeginOperation();
}
}
/*简单工厂模式*/
public class OrderSimpleFactory
{
private static IOrder order = null;
public static IOrder CreateOrderType(OrderType oType)
{
switch (oType)
{
default:
break;
case OrderType.Online:
order = new OnlineOrder();
break;
case OrderType.Telephone:
order = new TelephoneOrder();
break;
case OrderType.Counter:
order = new CounterOrder();
break;
}
return order;
}
}
/*简单工厂模式*/
public class PaySimpleFactory
{
private static IPay pay = null;
public static IPay CreatePayType(PayType pType)
{
switch (pType)
{
default:
break;
case PayType.Electronic:
pay = new ElectronicPay();
break;
case PayType.VirtualMoney:
pay = new VirtualMoneyPay();
break;
case PayType.Cash:
pay = new CashPay();
break;
}
return pay;
}
}
public class Program
{
static void Main(string[] args)
{
NormalUser nu = new NormalUser("jeff");
VipUser vu = new VipUser("Jeff Wong");
nu.BeginOperation(); //默认预订和支付方式
Console.WriteLine("---------------------------------------------------------------------------");
vu.BeginOperation(); //默认预订和支付方式
Console.WriteLine("---------------------------------------------------------------------------");
nu.SetOrderType(new TelephoneOrder());
nu.SetPayType(new VirtualMoneyPay());
//普通用户 更改预订方式和支付方式
vu.SetOrderType(new OnlineOrder());
vu.SetPayType(new ElectronicPay());
//VIP用户 更改预订方式和支付方式
nu.BeginOperation();
Console.WriteLine("---------------------------------------------------------------------------");
vu.BeginOperation();
Console.Read();
}
}
}
上面的实例中,IOrder和IPay相当于策略模式中的Strategy,继承它们的相当于具体算法ConcreteStrategy,而customer(或者继承它的)类相当于Context,维护对Strategy对象的引用。客户端调用时,可以设置不同的策略。
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。