定义
它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

- 算法之间可以互相调用
- 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
比如出行方式,商场打折等等,都可以用策略模式来封装。
代码实现
- 算法基类:Strategy类,定义所有支持的算法的公共接口
public abstract class Strategy
{
public abstract void AlgorithmInterface();
}
- 具体算法类:ConcreteStrategy,封装了具体的算法或行为,继承于Strategy
public class ConcreteStrategy1 : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法1的实现");
}
}
public class ConcreteStrategy2 : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法2的实现");
}
}
public class ConcreteStrategy3 : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法3的实现");
}
}
- 环境类(上下文类):Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
public class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
- 客户端调用:
class Program
{
static void Main(string[] args)
{
Context context;
context = new Context(new ConcreteStrategy1());
context.ContextInterface();
context = new Context(new ConcreteStrategy2());
context.ContextInterface();
context = new Context(new ConcreteStrategy3());
context.ContextInterface();
Console.ReadLine();
}
}

商场促销的例子
策略与简单工厂结合,把子类创建移到环境类中,直接用字符串来调用各种不同的策略。这样,客户端就不需要知道具体的算法类了。

- 基类:策略类,为抽象类,抽象出收费的方法供子类实现。
abstract class CashSuper {
public abstract double acceptCash(double money);
}
- 子类1:正常收费子类;没有任何活动的情况,正常收费,返回原价。
class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
- 子类2:打折收费子类;打折活动,根据折扣返回打折后的价格。
class CashRebate extends CashSuper {
//折扣
private double moneyRebate = 1;
// 类初始化的时候设置折扣率 0 ~ 1
public CashRebate(double moneyRebate) {
if (moneyRebate > 1) {
this.moneyRebate = 1;
return;
}
if (moneyRebate < 0) {
this.moneyRebate = 0;
return;
}
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * this.moneyRebate;
}
}
- 子类3:返利收费子类;返利活动,输入返利条件和返利值,比如满300返100,moneyCoditation为300,moneyReturn为100。
result = money - Math.floor(money / moneyConditation) * moneyReturn;
的意思为,如果当前金额大于等于返利条件,则使用当前金额减去返利值。
class CashReturn extends CashSuper {
private double moneyConditation = 0.0; //返利条件
private double moneyReturn = 0.0d; //返利值
public CashReturn(double moneyConditation, double moneyReturn) {
this.moneyConditation = moneyConditation;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
double result = money;
if (money >= moneyConditation) {
result = money - Math.floor(money / moneyConditation) * moneyReturn;
}
return result;
}
}
- 环境类:包装这些算法,方便客户端调用。
class CashContext {
private CashSuper cashSuper = null;
// 根据文字创建,相当于简单工厂
CashContext(String type) {
switch (type) {
case "正常收费":
cashSuper = new CashNormal();
break;
case "满300返100":
cashSuper = new CashReturn(300, 100);
break;
case "打8折":
cashSuper = new CashRebate(0.8);
break;
default:
cashSuper = new CashNormal();
break;
}
}
public double getResult(double money) {
return cashSuper.acceptCash(money);
}
}
- 客户端:先算原价,然后调用环境类的
getResult
接口,算出活动价。
public void onReturnButtonClick(View view) {
doCash("满300返100");
}
public void onRebateButtonClick(View view) {
doCash("打8折");
}
public void onNormalButtonClick(View view) {
doCash("普通收费");
}
private void doCash(String type) {
try {
double price = Double.parseDouble(priceEditText.getText().toString());
int count = Integer.parseInt(countEditText.getText().toString());
double money = price * count;
CashContext cashContext = new CashContext(type);
double result = cashContext.getResult(money);
this.totalTextView.setText(String.valueOf(result));
} catch (Exception e) {
e.printStackTrace();
}
}
- 运行一下:



Demo地址
https://gitee.com/zhangxusong888/Android/tree/master/design_pattern
网友评论