从简单模式到策略模式

  前面我们谈了简单工厂模式,下面我们谈一下策略模式。

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

它的优点有:

  1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)

  2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。

  3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

  缺点:

因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量

我们以商场收银来说明一下这个模式。

  商场收银软件需求很简单,营业员根据客户所购买商品的单价和数量,向客户收费。

  也许有些人会这么想,这个很简单,接受用户输入的的单价和数量,把他们相乘不就可以了嘛。当然,。,那当然可以。那如果商场对某些商品进行打折活动呢。也许你会说,那还不简单,让用户输入打几折不就行了嘛。计算总价时在原来的基础上乘以折扣就是客户的收费了。也许这个时候,你想到了封装,抽象,或者用我们以前的简单工厂模式来解决这个问题。代码如下:

 1;我们先写一个现金收费抽象类。

  public abstract class CashSuper {

   public abstract double acceptCash(double money);

}

2:正常收费子类,继承现金收费抽象类:

public class CashNormal extends CashSuper {

   public double acceptCash(double money){

       return money;

   }

}

 3:打折收费子类,继承现金收费抽象类

public class CashRebate extends CashSuper {

private double moneyRebate=0.0;//折扣

    @Override

    public double acceptCash(double money) {

        // TODO Auto-generated method stub

        return money*moneyRebate;

    }

    public CashRebate(String moneyRebate){

        this.moneyRebate=Double.parseDouble(moneyRebate);

    }

 

}

4:返利收费子类,如果客户满300100

 public class CashReturn extends CashSuper {

    private double moneyCondition=0;//返利条件

    private double moneyReturn=0;//返利

    public CashReturn(String moneyCondition,String moneyReturn ){

    this.moneyCondition=Double.parseDouble(moneyCondition);

    this.moneyReturn=Double.parseDouble(moneyReturn);

    }

    public double acceptCash(double money){

        double result=money;

        if(money>=moneyCondition)

            result=money-Math.floor(money/moneyCondition)*moneyReturn;

        return result;

    }

}

5:现金收费工厂类:

public class CashFactory {

    public static CashSuper createCashAccept(int type ){

        CashSuper cs=null;

        switch(type){

        case 1:

            //1表示正常收费

             cs=new CashNormal();

             break;

        case 2:

            //300100

            CashReturn cr1=new CashReturn("300","100");

            cs=cr1;

            break;

        case 3:

            //8

            CashRebate cr2=new CashRebate("0.8");

            cs=cr2;

            break;

           

        }

        return cs;

    }

 

}

6:测试类主要实例化工厂类,接受单价和数量,还有折扣和返利。

我们想想这是最好的办法吗?我们前面讲过,简单工厂模式虽然也能解决这类问题,但是我们知道这个模式只是解决对象的创建问题。而商场收银软件也许有可能会经常更改打折和返利,那我们是不是都要改动工厂呢?仔细想想,它打折和返利,只是算法的更改。为什么我们不用策略模式呢?

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

下面我们用策略模式和简单工厂的结合解决这个问题:

原来写的CashSuper,CashNormal,CashRebate,CashReturn都不用改了,我们再加一个类:

1cashContext类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。

public class CashContext {

    private CashSuper cs=null;

    public CashContext(int type){

        switch(type){

        case 1:

            //正常收费

            CashNormal cs1=new CashNormal();

            cs=cs1;

            break;

        case 2:

            //300返回100

            CashReturn cr2=new CashReturn("300","100");

            cs=cr2;

            break;

        case 3:

            CashRebate cr3=new CashRebate("0.8");

            cs=cr3;

            break;

           

        }

    }

    public double GetResult(double money){

        return cs.acceptCash(money);

    }

 

}

这样就可以了,其他的任务交给客户端就行了。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值