大话设计模式-第2章 商场促销--策略模式- 高飞网

第2章 商场促销--策略模式

2016-02-01 11:58:44.0

定义

策略模式(Strategy,[ˈstrætədʒi]:定义了算法的家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

策略模式中,各算法之间只能使用一种,因此是算法切换的好方法。
下图是策略模式的类图:


如上图:Strategy定义了算法接口,是算法的基类,它的三个子类分别以不同策略实现了这一接口。Context上下文类,它接收一个具体的实现策略,最终得到算法接口返回结果。

下面是基本代码。

public class App{
        public static void main(String[] args){
                Context c = null;
                c = new Context(new ConcreteStrategyA());
                c.contextInterface();
                c = new Context(new ConcreteStrategyB());
                c.contextInterface();
                c = new Context(new ConcreteStrategyC());
                c.contextInterface();

        }
}

public abstract class Strategy{
        public abstract void algorithmInterface();
} 

public class ConcreteStrategyA extends Strategy{
        public void algorithmInterface(){
                System.out.println("algorithm A...");
        }
}
public class ConcreteStrategyB extends Strategy{
        public void algorithmInterface(){
                System.out.println("algorithm B...");
        }
}

public class ConcreteStrategyC extends Strategy{
        public void algorithmInterface(){
                System.out.println("algorithm C...");
        }
}
public class Context{
        Strategy s = null;
        public Context(Strategy s){
                this.s = s;
        }
        public void contextInterface(){
                s.algorithmInterface();
        }
}

应用

    以上次简单工厂的促销活动为例,结合策略和简单工厂模式设计


/**
* 打折基类
* 策略类
*/
public abstract class CashSuper{
        public abstract double acceptCash(double money);       
}

/**
* 正常收费
* 具体策略类
*/
public class CashNormal extends CashSuper{
        public double acceptCash(double money){
                return money;
        }
}

/**
* 打折收费
* 具体策略类
*/
public class CashRebate extends CashSuper{
        private double moneyRebate = 1d;//打折
        public CashRebate(double moneyRebate){
                this.moneyRebate = moneyRebate;
        }
        public double acceptCash(double money){
                return moneyRebate * money;
        }
}

/**
* 返利
* 具体策略类
*/
public class CashReturn extends CashSuper{
       
        private double moneyCondition = 0.0d;
        private double moneyReturn = 0.0d;

        public CashReturn(double moneyCondition,double moneyReturn){
                this.moneyCondition = moneyCondition;
                this.moneyReturn = moneyReturn;
        }
        public double acceptCash(double money){
                if(money >= moneyCondition){
                        money = money - (int)(money / moneyCondition)* moneyReturn;
                }
                return money;
        }
}

/**
* 上下文,持有对具体策略的引用,这个类是简单工厂与策略模式的接合使用
*/
public class CashContext{

        private CashSuper cash = null;

        public CashContext(String type){
                CashSuper cash = null;
                switch(type){
                        case "正常收费":
                                cash = new CashNormal();
                        break;
                        case "满300返100":
                                cash = new CashReturn(300,100);
                        break;
                        case "打8折":
                                cash = new CashRebate(0.8d);
                        break;
                }  
                this.cash = cash;
        }

        public double getResult(double money){
                return this.cash.acceptCash(money);
        }
}

import java.io.*;
public class App{
        public static void main(String[] args)throws Exception{
                System.out.print("输入单价:");
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                double price = Double.parseDouble(br.readLine());
                System.out.print("输入数量:");
                br = new BufferedReader(new InputStreamReader(System.in));
                int count = Integer.parseInt(br.readLine());
                System.out.print("输入打折方式:");
                br = new BufferedReader(new InputStreamReader(System.in));
                String type = br.readLine();

                double money = price * count ;
                CashContext context = new CashContext(type);
                double total = context.getResult(money);
                System.out.println("总计:"+total);
        }
}


比较简单工厂与策略模式:

简单工厂模式  
简单工厂+策略模式  
CashSuper cash = CashFactory.createCashAccept(type);
double total = cash.acceptCash(money);
  
CashContext context = new CashContext(type);
double total = context.getResult(money);
  
识两个类:CashSuper和CashFactory  
只要认识一个CashContext即可  

即:使用简单工厂时,要把接口暴露给客户端,而使用策略模式,则对客户端完全隐藏了算法的细节。


总结


策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法与使用算法类之间的耦合。
策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中公共功能。
策略模式封装了算法的变化。

不足,即便使用了上面的设计模式, 再增加一种算法时,依然需要修改CashContext上下文类。