策略模式(Strategy):它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)
应用场景: 1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
关于策略模式,还是来一个小例子吧,大家都知道超市或者网上商城里面经常有各种打折活动,如果我们写一个收费计算系统,关于这块代码怎么设计才好呢?因为打折活动各种情况,各种不同,如何写能够在打折活动修改的时候减少代码的修改,减少出差的概率呢?
想想使用下策略模式:
先看下可以独立出系统的善变的打折接口:
public interface IDiscount { double getPrice(double price, int quantity); }
下面是实现接口的两个打折方法:一、直接打折
public class Rebate implements IDiscount { private double discount; public void setDiscount(double discount){ this.discount = discount; } public double getDiscount(){ return discount; } @Override public double getPrice(double price, int quantity) { // TODO Auto-generated method stub return price*quantity*discount; } }二、达到一定数额返现金
public class CashReturn implements IDiscount { private int cashCondition; private int cashReturn; public void setCondition(int cashCondition,int cashReturn){ this.cashReturn = cashReturn; this.cashCondition = cashCondition; } @Override public double getPrice(double price, int quantity) { double orignal = price * quantity; int n = (int) (orignal / cashCondition); return orignal - cashReturn * n; } }收银机:
public class CashRegister { private IDiscount iDiscount; public void setDiscount(IDiscount iDiscount){ this.iDiscount = iDiscount; } public void getAccountReceivable(double price, int quantity){ System.out.println("应收:"+iDiscount.getPrice(price,quantity)); } }
测试:
public static void main(String[] args){ //两种折扣方式 IDiscount rebate = new Rebate(); IDiscount cashReturn = new CashReturn(); CashRegister cashRegister = new CashRegister(); //使用打折 ((Rebate) rebate).setDiscount(0.8); cashRegister.setDiscount(rebate); cashRegister.getAccountReceivable(102.8, 3); //返现金 ((CashReturn) cashReturn).setCondition(200,40); cashRegister.setDiscount(cashReturn); cashRegister.getAccountReceivable(102.8, 3); }
结果:
优点:
缺点: 1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
listView.setAdapter(),里面的Adapter ,一般都是自定义的Adapter ,继承自BaseAdapter ,这就是典型的策略模式,当ListView 的Item呈现不同形式,在getView方法中,就得不同的实现。